[swift] 일반 메서드에서 프로토콜 기본 구현 호출

그런 일을 할 수 있는지 궁금합니다.
다음과 같은 놀이터가 있습니다.

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모든 항목과 추가 항목이 필요한 경우 어떻게 해야합니까? 모든 속성 등을 구현하는 요구 사항을 충족하기 위해 es에서 메서드
를 호출 super.하는 것과 비슷 class하지만 structs.



답변

여전히 이것에 대한 답을 찾고 있는지는 모르겠지만, 그 방법은 프로토콜 정의에서 함수를 제거하고 객체를 캐스트 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"

어떤 이유로 함수가 프로토콜의 일부로 선언되지 않고 프로토콜에 대한 확장으로 정의 된 경우에만 작동합니다. 그림을 이동. 하지만 작동합니다.


답변

글쎄, 당신은 프로토콜을 준수하는 중첩 된 유형을 만들고, 인스턴스화하고, 그 유형에 대한 메서드를 호출 할 수 있습니다 (프로토콜 확장 내부의 구현이 어쨌든 그것을 참조 할 수 없기 때문에 유형의 데이터에 액세스 할 수 없다는 것은 중요하지 않습니다). 그러나 그것은 내가 우아하다고 부르는 해결책이 아닙니다.

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


답변

게시물 주셔서 감사합니다! 프로토콜에 함수 정의를 넣으면 객체가 프로토콜로 캐스팅 될 때 객체의 함수 버전 만 볼 수 있으며 자체 내부에서 호출하므로 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


답변

프로토콜에 associatedType또는 Self요구 사항 이있는 경우 캐스트가 작동하지 않습니다. 이 문제를 해결하려면 일반 기본 구현과 준수 유형이 모두 호출 할 수있는 “그림자”기본 구현을 만듭니다.

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()
    }
}


답변

이러한 문제를 해결하는 방법에 대해 어떻게 생각하십니까?

protocol Foo {
    func testPrint()
}

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

    func defaultTestPrint() {
        print("Protocol extension call")
    }
}

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


let sth = Bar()
sth.testPrint()


답변