从常规方法

时间:2015-09-16 07:51:29

标签: swift oop protocols swift2

我想知道是否有可能实现这样的目标 我有一个像这样的游乐场:

protocol Foo {
    func testPrint()
}

extension Foo {
    func testPrint() {
        print("Protocol extension call")
    }
}

struct Bar: Foo {
    func testPrint() {
        // Calling self or super go call default implementation
        self.testPrint()
        print("Call from struct")
    }
}


let sth = Bar()
sth.testPrint()

我可以在extension中提供默认实现,但如果Bar需要默认实现中的所有内容以及其他内容,该怎么办? 它在某种程度上类似于在super. es中调用class方法来满足实现每个属性等的要求,但我认为不可能用structs实现相同的目标。

6 个答案:

答案 0 :(得分:77)

我不知道您是否还在寻找答案,但是这样做的方法是从协议定义中删除该函数,将您的对象转换为Foo,然后调用该方法它:

protocol Foo { 
    // func testPrint() <- comment this out or remove it
}

extension Foo {
    func testPrint() {
        print("Protocol extension call")
    }
}

struct Bar: Foo {
    func testPrint() {
        print("Call from struct")
        (self as Foo).testPrint() // <- cast to Foo and you'll get the  default
                                  //    function defined in the extension
    }
}

Bar().testPrint()

// Output:    "Call from struct"
//            "Protocol extension call"

由于某种原因,它仅在函数未声明为协议的一部分时才有效,但在协议的扩展中定义。去搞清楚。但它确实有效。

答案 1 :(得分:7)

好吧,你可以创建一个符合协议的嵌套类型,实例化它,然后在那个上调用方法(由于协议扩展中的实现无论如何都无法引用它,因此无法访问类型的数据并不重要) 。但这不是我称之为优雅的解决方案。

struct Bar: Foo {
    func testPrint() {
        // Calling default implementation
        struct Dummy : Foo {}
        let dummy = Dummy()
        dummy.testPrint()
        print("Call from struct")
    }
}

答案 2 :(得分:2)

谢谢你的帖子!如果你把函数定义放在协议中,那么当对象作为协议进行转换时,它只能看到对象的函数版本,因为你在内部调用它,你就得到了Apple的新地址......

我确实试过这样的版本:

import UIKit
protocol MyProc
{
}

protocol MyFuncProc
{
    func myFunc()
}

extension MyProc
{
    func myFunc()
    {
        print("Extension Version")
    }
}

struct MyStruct: MyProc, MyFuncProc
{
    func myFunc()
    {
        print("Structure Version")
        (self as MyProc).myFunc()
    }
}

(MyStruct() as MyFuncProc).myFunc()

这给出了输出:

Structure Version
Extension Version

答案 3 :(得分:2)

如果您的协议具有associatedTypeSelf的要求,则强制转换将不起作用。要解决此问题,请创建一个“阴影”默认实现,常规默认实现和符合性类型都可以调用。

protocol Foo { 
    associatedType Bar
}

extension Foo {
    func testPrint() {
        defaultTestPrint()
    }
}

fileprivate extension Foo { // keep this as private as possible
    func defaultTestPrint() {
        // default implementation
    }
}

struct Bar: Foo {
    func testPrint() {
        // specialized implementation
        defaultTestPrint()
    }
}

答案 4 :(得分:2)

我为此提出了一个解决方案。

问题

在扩展中具有默认实现时,在将协议实现到另一个类/结构时,如果实现该方法,则会丢失此默认实现。这是设计使然,这就是协议的工作方式

解决方案

  • 创建协议的默认实现,并将其设置为协议的属性。
  • 然后,当您在类中实现此协议时,请为默认实现提供getter。
  • 在需要时调用默认实现。

示例


protocol Foo {
    var defaultImplementation: DefaultImpl? { get }
    func testPrint()
}

extension Foo {
    // Add default implementation
    var defaultImplementation: DefaultImpl? {
        get {
            return nil
        }
    }
}

struct DefaultImpl: Foo {
    func testPrint() {
        print("Foo")
    }
}


extension Foo {
    
    func testPrint() {
        defaultImplementation?.testPrint()
    }
}

struct Bar: Foo {
    
    var defaultImplementation: DefaultImpl? {
        get { return DefaultImpl() }
    }
    func testPrint() {
        if someCondition {
            defaultImplementation?.testPrint() // Prints "Foo"
        }
    }
}

struct Baz: Foo {
    func testPrint() {
        print("Baz")
    }
}


let bar = Bar()
bar.testPrint() // prints "Foo"

let baz = Baz()
baz.testPrint() // prints "Baz"


缺点

您在实现此协议的结构/类中丢失了必需的实现错误。

答案 5 :(得分:1)

您如何看待这种解决方法?

id   pc_no cust_id   event_id event_date    event_mark  event_rep    loc_id
1    51     NA       CC       2018-08-15    SE          DELL         IBM      
3    53     NA       CC       2018-08-17    SD          UNK          SUW
4    54     NA       CC       2018-08-18    SF          DELL         ACER