일반 메서드에서 프로토콜 기본 구현 호출
저는 그런 일이 가능한지 궁금합니다.
다음과 같은 Playground가 있습니다.
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.
의 방법.class
es 모든 재산 등을 이행하는 요건을 충족시키지만, 저는 동일한 것을 달성할 가능성이 없다고 봅니다.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")
}
}
당신은 이것을 고치는 그런 방법에 대해 어떻게 생각합니까?
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()
게시물 감사합니다!함수 정의를 프로토콜에 넣으면 개체가 프로토콜로 캐스팅될 때 개체의 함수 버전만 표시되고 사용자가 내부에서 호출하므로 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()
}
}
저는 이것에 대한 해결책을 생각해냈습니다.
쟁점.
확장에 기본 구현이 있는 경우 다른 클래스/구조체에 프로토콜을 구현할 때 메소드를 구현하면 이 기본 구현이 손실됩니다.이것은 의도적으로, 이것이 프로토콜이 작동하는 방법입니다.
해결책
- 프로토콜의 기본 구현을 만들어 프로토콜의 속성으로 만듭니다.
- 그런 다음 클래스에서 이 프로토콜을 구현할 때 기본 구현을 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"
단점
이 프로토콜을 구현하는 구조/클래스에서 필요한 구현 오류가 손실됩니다.
언급URL : https://stackoverflow.com/questions/32602712/calling-protocol-default-implementation-from-regular-method
'programing' 카테고리의 다른 글
다른 워크북에서 셀에 대한 참조를 감지하고 있습니까? (0) | 2023.09.05 |
---|---|
Chrome Extension 콘텐츠 스크립트에서 popup.html로 데이터를 보내는 방법 (0) | 2023.09.05 |
HTTP 헤더에 사용된 날짜/시간 형식 (0) | 2023.09.05 |
Python 및 MySQLDB를 사용하여 mysql 데이터베이스에서 테이블 이름을 검색하는 방법은 무엇입니까? (0) | 2023.09.05 |
spring-boot에서 업데이트를 위해 select를 사용하는 방법 (0) | 2023.09.05 |