如何说“同一类”在一个Swift通用 [英] how to say "same class" in a Swift generic

查看:79
本文介绍了如何说“同一类”在一个Swift通用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果一个Swift泛型类型约束是一个协议名称,我可以要求两种类型,约束到该协议,是相同的类型。例如:

  protocol Flier {} 
struct Bird:Flier {}
struct Insect:Flier { }
func flockTwoTogether< T:Flier>(f1:T,f2:T){}

函数 flockTwoTogether 可以用Bird和Bird调用,或者用Insect和Insect调用,但不能用Bird和Insect调用。这是我想要的限制。到目前为止,这么好。



然而,如果我用类名尝试同样的事情,它不起作用:

  class Dog {} 
class NoisyDog:Dog {} $ b $ class WellBehavedDog:Dog {}
func walkTwoTogether< T:Dog>( d1:T,d2:T){}

问题是我可以调用 walkTwoTogether 与一个WellBehavedDog和一个NoisyDog。这是我想要防止的。



这里有两个问题:


  • 有没有办法说 walkTwoTogether 不能用WellBehavedDog和NoisyDog调用?


  • 这是一个错误吗?我问,因为如果我不能用泛型来表达这一点,很难理解为什么泛型约束完全可以用作类名,因为我们可以用普通函数得到相同的结果。 / p>



解决方案

或许... 问题出在你打电话时:

  walkTwoTogether(NoisyDog(),WellBehavedDog())

Swift可以将两个实例视为它们是 Dog (aka,upcast) - 我们需要这个,所以我们可以调用类 A 的子类为 A 。 (我知道你知道这一点。)



Swift不会上传到协议,所以唯一的方法就是为子类指定一个协议, em>不符合:

 协议可步行{} 
分机NoisyDog:Walkable {}
extension WellBehavedDog:Walkable {}
func walkTwoTogether< T:Dog where T:Walkable>(d1:T,d2:T){}

walkTwoTogether(NoisyDog(), WellBehavedDog())
//错误:输入'Dog'不符合协议'Walkable'

错误消息明确显示了发生了什么 - 调用此版本的 walkToTogether 的唯一方法是将子类实例上传到 Dog ,但 Dog 不符合可走行


If a Swift generic type constraint is a protocol name, I can require that two types, constrained to that protocol, be the same type. For example:

protocol Flier {}
struct Bird : Flier {}
struct Insect: Flier {}
func flockTwoTogether<T:Flier>(f1:T, f2:T) {}

The function flockTwoTogether can be called with a Bird and a Bird or with an Insect and an Insect, but not with a Bird and an Insect. That is the limitation I want. So far, so good.

However, if I try the same thing with a class name, it doesn't work:

class Dog {}
class NoisyDog : Dog {}
class WellBehavedDog: Dog {}
func walkTwoTogether<T:Dog>(d1:T, d2:T) {}

The problem is that I can call walkTwoTogether with a WellBehavedDog and a NoisyDog. This is what I want to prevent.

There are really two questions here:

  • Is there a way to say that walkTwoTogether can't be called with a WellBehavedDog and a NoisyDog?

  • Is this a bug? I ask because if I can't use a generic to say this, it is hard to see why it is useful for a generic constraint to be a class name at all, since we could get the same result just with a normal function.

解决方案

Not an answer, per se, but some more data perhaps... The problem is when you call:

walkTwoTogether(NoisyDog(), WellBehavedDog())

Swift can just treat both instances as if they're instances of Dog (aka, upcast) — we need that so we can call methods meant for class A with subclasses of A. (I know you know this.)

Swift doesn't upcast to protocols, so the only way to do it is to specify a protocol for the subclasses that the superclass doesn't conform to:

protocol Walkable {}
extension NoisyDog : Walkable {}
extension WellBehavedDog: Walkable {}
func walkTwoTogether<T: Dog where T: Walkable>(d1:T, d2:T) { }

walkTwoTogether(NoisyDog(), WellBehavedDog())
// error: type 'Dog' does not conform to protocol 'Walkable'

The error message explicitly shows what is going on — the only way to call this version of walkToTogether is to upcast the subclass instances to Dog, but Dog doesn't conform to Walkable.

这篇关于如何说“同一类”在一个Swift通用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆