如何说“同一类”在一个Swift通用 [英] how to say "same class" in a Swift generic
问题描述
如果一个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。这是我想要防止的。
这里有两个问题: 有没有办法说 这是一个错误吗?我问,因为如果我不能用泛型来表达这一点,很难理解为什么泛型约束完全可以用作类名,因为我们可以用普通函数得到相同的结果。 / p>
walkTwoTogether
不能用WellBehavedDog和NoisyDog调用?
或许... 问题出在你打电话时:
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屋!