我最近一直在涉及Swift,而且我遇到了一个奇怪的绊脚石,类型限制没有像我预期的那样运行(相比之下,Scala)。
protocol Foo {
typealias T: Hashable
func somethingWithT() -> T
}
struct Bar: Foo {
typealias T = Int
func somethingWithT() -> T { return 1 }
}
func baz() -> [Foo] {
var myBars = [Foo]()
myBars.append(Bar())
return myBars
}
这会在XCode中引发错误:
有什么想法在这里发生了什么?我希望T
可以作为字典中的密钥使用,但是从我读过的Hashable
引用Self
某处,所以它只能被使用作为一般约束,从而消除了我只有[Foo]
的能力。
我想要列出Foo
的内容,但是按照这个速度,似乎我必须删除Hashable
约束或使其不那么通用..
我试过清理我的项目并重新制作,但没有骰子:(
答案 0 :(得分:2)
这里的问题是必须在运行时知道ImageView pic2;
TextView score;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pic2 = (ImageView) findViewById(R.id.imageView1);
score = (TextView) findViewById(R.id.textView2);
(协议)的类型。由于缺少带有类型别名的泛型,您可以通过制作T
类型(如标准库AnyFoo
和AnyGenerator
)来解决这个问题:
AnySequence
这不是通用功能,但您可以将具有相同protocol Foo {
typealias T: Hashable
func somethingWithT() -> T
}
struct AnyFoo<T: Hashable>: Foo {
let function: () -> T
init<F: Foo where F.T == T>(_ foo: F) {
// storing a reference to the function of the original type
function = foo.somethingWithT
}
func somethingWithT() -> T {
return function()
}
}
struct Bar: Foo {
typealias T = Int
func somethingWithT() -> T { return 1 }
}
// instead of returning [Foo] you can return [AnyFoo<Int>]
func baz() -> [AnyFoo<Int>] {
var myBars = [AnyFoo<Int>]()
// converting the type or Bar
myBars.append(AnyFoo(Bar()))
return myBars
}
的任何Foo
类型转换为相同的T
类型
答案 1 :(得分:0)
myBars是T:Foo的数组。你当然可以传入一个Bar,因为它满足了对T的约束。但是另一个具体类型也是如此。由于T必须是具体的类型,你不能任意地在那里放置一个Bar,而不保证你唯一放在那里的是Bars。使用此函数签名在Swift中执行此操作的唯一方法是传入一个Bar。
我想也许你想要的是一组协议对象,而不是通用数组。