【问题标题】:Define a variable that conforms to more than one protocol/protocol+superclass定义一个符合多个协议/协议+超类的变量
【发布时间】:2015-01-16 19:28:01
【问题描述】:

我正在尝试在类型之间实现一种不平凡的(至少对于我的级别而言)关系。

A 类和 B 类是 MySuperClass 类的子类,我让它们实现协议“MyProtocol”

class MySuperclass {...}

protocol MyProtocol {
     func myProtocolMethod() 
}

class A:MySuperclass, MyProtocol {...}

class B:MySuperclass, MyProtocol {...}

我的“容器”类有一个变量 x,它可以是 A 或 B 的实例

class Container {... var x:???? ....}

从 ????我的问题是我希望我可以将 x 用作 MyProtocol 和 MySuperclass。

就在今天,我在this thread 中解决了一个非常相似的问题,我想我可以在这里应用它,但我没有成功。

我们的想法是声明变量的类型,使其满足约束<T where T:MySuperclass, T:MyProtocol>,但我应该把它放在哪里?到目前为止我所尝试的一切都没有真正的意义并且失败了。

我试过了,例如:

class Container<T where T:MySuperclass, T:MyProtocol>

class Container {... var x:T ...}

但我在Container 中实例化并分配 T,当我这样做时,我得到一个编译器错误:

class Container {... self.x = A() ....}

“类型 A 不能转换为 'T'”

但实际上应该,因为 A 满足类型约束。

编辑:感谢arshajii's anwer 我明白为什么这是不可能的。但我仍然需要知道如何解决我最初的问题。

我不知道泛型是否真的是正确的方法。我想我并不真的需要一个类型变量,我需要的是一个聚合类型之类的东西......

编辑 2- 我知道我可以通过实现一个子类来实现这一点。只是想知道是否有其他方法。但重新考虑子类似乎是最好的方法。

提前致谢。

【问题讨论】:

    标签: generics swift


    【解决方案1】:

    T 可能是与FooImpl 完全无关的另一种类型(例如FooImpl2):

    富 / \ FooImpl FooImpl2

    无法将Foo 实例分配给FooImpl2 类型的(潜在)变量,因此会出现错误。

    【讨论】:

    • 谢谢! (+1)现在我明白了。但我仍然不知道如何解决我原来的问题:/ 也许我应该删除 Java 标记,因为该解决方案需要 Swift 专业知识。
    【解决方案2】:

    这只是解决此类问题的策略之一。

    // declare Protocol of MySuperClass type
    protocol MySuperClassType {
        func mySuperClassMethod()
    }
    
    // Make the superclass conforms to it.
    class MySuperclass: MySuperClassType {
    //                  ^^^^^^^^^^^^^^^^
        func mySuperClassMethod() {}
    }
    
    protocol MyProtocol {
        func myProtocolMethod()
    }
    
    class A: MySuperclass, MyProtocol {
        func myProtocolMethod() { }
    }
    
    class B: MySuperclass, MyProtocol {
        func myProtocolMethod() { }
    }
    
    class Container {
    
        // use "Protocol Composition" to declare the property.
        var x: protocol<MySuperClassType, MyProtocol>
    
        // ...
    }
    

    【讨论】:

    • 在我的特殊情况下,这个问题是我希望现有 api 可以将变量用作 MySuperClass 的实例。一个例子:如果 MySuperClass 是一个 UIView,即使我使用 UIView 方法创建一个扩展以使 x 符合协议“MySuperClassType”,我也无法执行 view.addSubview(x)。
    • 那你应该采取另一种策略,比如:stackoverflow.com/questions/26474061/…
    【解决方案3】:
    class Container {... var x: protocol<MySuperclassProtocol, MyProtocol> ....}
    

    确保MySuperclass 符合MySuperclassProtocol

    【讨论】:

    • 在我的特殊情况下,这个问题是我希望现有 api 可以将变量用作 MySuperClass 的实例。一个例子:如果 MySuperClass 是一个 UIView,即使我使用 UIView 方法创建一个扩展以使 x 符合协议“MySuperClassType”,我也无法执行 view.addSubview(x)。
    • view.addSubview(unsafeBitCast(x, UIView.self))
    • 我假设您不知道unsafeBitCast。我已经尝试自己解决这个问题,但还没有找到具体的解决方案。
    • Swift 协议目前还不支持子类依赖。
    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多