我想知道是否有可能实现这样的事情。
我有一个这样的游乐场:
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
中调用super.
方法来满足实现每个属性等的要求,但我认为没有可能实现与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"
缺点
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"
在实现该协议的结构/类中丢失了所需的实现错误