Вызов реализации протокола по умолчанию из обычного метода
Я интересно, если это возможно, чтобы достичь такой вещи.
У меня есть площадка, как это:
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
Эс для того чтобы выполнить требование снабжать каждое свойство ЕТК. но я не вижу возможности добиться того же с structs
.
4 ответа:
Я не знаю, если вы все еще ищете ответ на этот вопрос, но способ сделать это-удалить функцию из определения протокола, приведите свой объект к
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() } }