从常规方法调用协议默认实现
Calling protocol default implementation from regular method
我想知道是否有可能实现这样的事情。
我有一个这样的游乐场:
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
需要默认实现中的所有内容以及其他内容怎么办?
它有点类似于在 class
es 中调用 super.
方法来满足实现每个 属性 等的要求,但我认为 structs
.[=16 不可能实现相同的目标=]
好吧,您可以创建一个符合协议的嵌套类型,实例化它,然后调用该类型的方法(您不能访问您的类型的数据并不重要,因为协议扩展中的实现无法引用它反正)。但这不是我称之为优雅的解决方案。
struct Bar: Foo {
func testPrint() {
// Calling default implementation
struct Dummy : Foo {}
let dummy = Dummy()
dummy.testPrint()
print("Call from struct")
}
}
我不知道你是否还在寻找这个问题的答案,但方法是从协议定义中删除该函数,将你的对象转换为 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"
出于某种原因,它仅在函数未声明为协议的一部分但在协议的扩展中定义时才有效。去搞清楚。但它确实有效。
感谢post!如果将函数定义放在协议中,那么当对象被转换为协议时,它只会看到对象的函数版本,并且由于您是在自身内部调用它,因此您会获得 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
要求,则转换将不起作用。要解决此问题,请创建一个 "shadow" 默认实现,常规默认实现和符合类型都可以调用它。
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()
我想出了解决办法。
问题
当您在扩展中有一个默认实现时,当您将协议实现到另一个 class/struct 时,如果您实现了该方法,您将失去这个默认实现。这是设计使然,这就是协议的工作方式
解决方案
- 创建协议的默认实现并使其成为协议的 属性。
- 然后当您在 class 中实现此协议时,为您的默认实现提供 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"
缺点
您在实现此协议的 struct/class 中丢失了所需的实现错误。
我想知道是否有可能实现这样的事情。
我有一个这样的游乐场:
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
需要默认实现中的所有内容以及其他内容怎么办?
它有点类似于在 class
es 中调用 super.
方法来满足实现每个 属性 等的要求,但我认为 structs
.[=16 不可能实现相同的目标=]
好吧,您可以创建一个符合协议的嵌套类型,实例化它,然后调用该类型的方法(您不能访问您的类型的数据并不重要,因为协议扩展中的实现无法引用它反正)。但这不是我称之为优雅的解决方案。
struct Bar: Foo {
func testPrint() {
// Calling default implementation
struct Dummy : Foo {}
let dummy = Dummy()
dummy.testPrint()
print("Call from struct")
}
}
我不知道你是否还在寻找这个问题的答案,但方法是从协议定义中删除该函数,将你的对象转换为 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"
出于某种原因,它仅在函数未声明为协议的一部分但在协议的扩展中定义时才有效。去搞清楚。但它确实有效。
感谢post!如果将函数定义放在协议中,那么当对象被转换为协议时,它只会看到对象的函数版本,并且由于您是在自身内部调用它,因此您会获得 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
要求,则转换将不起作用。要解决此问题,请创建一个 "shadow" 默认实现,常规默认实现和符合类型都可以调用它。
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()
我想出了解决办法。
问题
当您在扩展中有一个默认实现时,当您将协议实现到另一个 class/struct 时,如果您实现了该方法,您将失去这个默认实现。这是设计使然,这就是协议的工作方式
解决方案
- 创建协议的默认实现并使其成为协议的 属性。
- 然后当您在 class 中实现此协议时,为您的默认实现提供 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"
缺点
您在实现此协议的 struct/class 中丢失了所需的实现错误。