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