【问题标题】:Extend existing protocols to implement another protocol with default implements扩展现有协议以使用默认实现实现另一个协议
【发布时间】:2016-05-19 14:28:51
【问题描述】:

是否可以通过扩展将协议合规性添加到不同的协议?

例如我们希望 A 遵守 B:

protocol A {
  var a : UIView {get}
}

protocol B {
  var b : UIView {get}
}

我想为 A 类型的对象提供 B 的默认实现(合规性)

// This isn't possible
extension A : B {
  var b : UIView {
    return self.a
  }
}

动机是在不需要创建我自己的“桥梁”的情况下需要 B 的情况下重用 A 的对象

class MyClass {
  func myFunc(object : A) {
    ...
    ...
    let view = object.a 
    ... do something with view ...

    myFunc(object)      // would like to use an 'A' without creating a 'B'
  }

  func myFunc2(object : B) {
    ...
    ...
    let view = object.b
    ... do something with view ...

  }
}

顺便说一句,我们可以扩展一个类来实现协议

class C {
  let C : UIView
}

// this will work
extension C : B {
  var B : UIView {
    return self.c
  }
}

协议可以提供默认实现

extension A {
  // a default implementation
  var a : UIView {
     return UIView()
  }
}

【问题讨论】:

    标签: swift protocols protocol-extension


    【解决方案1】:

    扩展A时,可以指定类型也符合B

    extension A where Self: B {
        var b : UIView {
            return self.a
        }
    }
    

    然后让你的类型符合AB,例如

    struct MyStruct : A, B {
        var a : UIView {
            return UIView()
        }
    }
    

    由于协议扩展,MyStruct 的实例将能够使用ab,即使在MyStruct 中仅实现了a

    let obj = MyStruct()
    obj.a
    obj.b
    

    【讨论】:

    • 我过去使用过“where Self:B...”,但它仍然需要定义您的“MyStruct”。 “MyStruct”是一个“一次性”的桥梁,它需要样板代码。我正在寻找最简洁的方式,这样我就不必创建中间构造来执行映射。理想情况下,我可以像扩展类或结构一样扩展协议。
    • 我有点困惑,在那种情况下你能不能结合使用where Self:B 和协议扩展?
    • @ABakerSmith 你试过编译上面的代码吗?我也尝试过这种方法,但编译器仍然一直告诉 MyStruct 不符合协议 B。我的协议 B 来自第三方并用 Objective C 编写。
    • @Flow,是的,代码为我编译。确定您在A 的扩展中正确实现了协议B 的要求吗?
    • @ABakerSmith 感谢您的回复。它确实在我的演示项目中使用纯 Swift 编译。但是,我发现,如果在 Objective-C 中声明协议 B,项目将无法编译。 (不幸的是我的情况,协议来自第三方)我在这里创建了一个演示项目github.com/linktoming/Protocol-Demo 协议C是在演示中用Objective-C编写的。
    【解决方案2】:

    你可以让A继承来自B:

    protocol A: B { var a: String { get } }
    protocol B    { var b: String { get } }
    
    // Default implementation of property b
    extension A {
        var b: String { get { return "PropertyB" } }
    }
    
    
    class MyClass: A {
        var a: String { get { return "PropertyA" } }
    
        func printA(obj: A) {
            print(obj.a)
            printB(obj)
        }
    
        func printB(obj: B) {
            print(obj.b)
        }
    }
    
    let obj = MyClass()
    obj.printA(obj)
    

    由于A 继承自BB 中的每个属性都可以在A 中使用。

    【讨论】:

    • 这与 OP 所要求的根本不同。如果他无法控制AB,这将无济于事。
    • 那我想你可以创建一个协议C 实现AB,根据需要使用默认实现?
    • 我不想创建额外的协议。
    • 那你问的是XY question
    • @CodeDifferent 你试过编译上面的代码吗?我正在尝试相同的方法,但编译器一直告诉 A 类不符合 Swift 2 中的协议 B。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多