gpt4 book ai didi

generics - 为什么泛型不能编译?

转载 作者:IT王子 更新时间:2023-10-29 05:05:04 27 4
gpt4 key购买 nike

我正在尝试使用泛型实现以下结构。遇到编译器错误,无法找出原因。

class Translator<T:Hashable> {...}

class FooTranslator<String>:Translator<String> {...}

想法是 Translator 使用 T 作为字典中键的类型。这可以是例如一个字符串或一个枚举。子类提供具体字典。

但它失败了,因为:“类型‘String’不符合协议(protocol)‘Hashable’”

但是String符合Hashable。它也不适用于同样符合 Hashable 的 Int。

如果我删除类型约束,只是为了测试(我还必须禁用字典,因为我不能使用任何不可散列的东西作为那里的键)- 它编译

class Translator<T> {...}

class FooTranslator<String>:Translator<String> {...}

我做错了什么?

最佳答案

首先,让我们解释一下错误:

给定:

class Foo<T:Hashable> { }

class SubFoo<String> : Foo<String> { }

这里令人困惑的部分是我们期望“String”表示 Swift 定义的结构,它包含一个字符集合。但事实并非如此。

这里,“String”是我们赋予新子类 SubFoo 的泛型类型的名称。如果我们进行一些更改,这将变得非常明显:

class SubFoo<String> : Foo<T> { }

此行为 T 生成错误,因为使用了未声明的类型。

然后如果我们把这一行改成这样:

class SubFoo<T> : Foo<T> { }

我们又回到了您最初遇到的相同错误,“T”不符合“Hashable”。在这里很明显,因为 T 不是恰好符合“Hashable”的现有 Swift 类型的名称。很明显,“T”是泛型。

当我们写 'String' 时,它也只是泛型类型的占位符名称,而不是 Swift 中实际存在的 String 类型。


如果我们想为泛型类的特定类型取一个不同的名字,合适的方法几乎肯定是 typealias:

class Foo<T:Hashable> {

}

typealias StringFoo = Foo<String>

这是完全有效的 Swift,它编译得很好。


如果相反,我们想要的是实际子类化并向泛型类添加方法或属性,那么我们需要的是一个类或协议(protocol),使我们的泛型更符合我们的需要。

回到最初的问题,我们先把错误去掉:

class Foo<T: Hashable>

class SubFoo<T: Hashable> : Foo<T> { }

这是完全有效的 Swift。但它对我们正在做的事情可能不是特别有用。

我们无法做到以下几点的唯一原因:

class SubFoo<T: String> : Foo<T> { }

只是因为 String 不是 Swift 类——它是一个结构。这对于任何结构都是不允许的。


如果我们编写一个继承自 Hashable 的新协议(protocol),我们可以使用它:

protocol MyProtocol : Hashable { }

class Foo<T: Hashable> { }
class SubFoo<T: MyProtocol> : Foo<T> { }

这是完全正确的。

另外,请注意我们实际上不必继承Hashable:

protocol MyProtocol { }
class Foo<T: Hashable> { }
class SubFoo<T: Hashable, MyProtocol> { }

这也是完全正确的。

但是请注意,无论出于何种原因,Swift 都不允许您在此处使用类。例如:

class MyClass : Hashable { }

class Foo<T: Hashable> { }
class SubFoo<T: MyClass> : Foo<T> { }

Swift 神秘地提示“T”不符合“Hashable”(即使我们添加了必要的代码来实现它)。


最后,正确的方法,也是最适合 Swift 的方法是编写一个新的协议(protocol),该协议(protocol)继承自“Hashable”并向其添加您需要的任何功能。

我们的子类接受一个 String 应该不是严格意义上的重要。重要的是,无论我们的子类采用什么,它都具有我们正在做的任何事情所需的必要方法和属性。

关于generics - 为什么泛型不能编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27920521/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com