そのようなことを達成することが可能かどうか疑問に思っています。
このようなプレイグラウンドがあります:
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")
}
}
投稿いただきありがとうございます!プロトコルに関数定義を配置すると、オブジェクトがプロトコルとしてキャストされると、オブジェクトのバージョンの関数のみが表示され、内部で呼び出すため、新しいアドレス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()