1

私は、swift、OOP、および POP についてすべて学んでいます。予期しない動作に遭遇したとき、それらを混ぜ合わせて抽象基本クラスを作成していました。これはコードで表現するのが最適です。期待どおりに動作することを示し、次に予想外の動作を示します (少なくとも私には)。コードは長いですが、単純です。ここでは正常に動作しています:

protocol GodsWill           {          func conforms() }
extension GodsWill          {          func conforms() { print("Everything conforms to God's Will") } }
class TheUniverse: GodsWill {          func conforms() { print("The Universe conforms to God's Will") } }
class Life: TheUniverse     { override func conforms() { print("Life conforms to God's Will") } }
class Humans: Life          { override func conforms() { print("Though created by God, Humans think they know better") } }

let universe = TheUniverse()
let life = Life()
let humans = Humans()

universe.conforms()
life.conforms()
humans.conforms()
print("-------------------------")
let array:[GodsWill] = [universe,life,humans]
for item in array { item.conforms() }

出力は次のとおりです。

The Universe conforms to God's Will
Life conforms to God's Will
Though created by God, Humans sometimes think they know better
-------------------------
The Universe conforms to God's Will
Life conforms to God's Will
Though created by God, Humans sometimes think they know better

これはまさに私が疑うとおりです。しかし、次のように、最初のクラスに conforms() のカスタム実装がなかったときに、アプリでこの問題に遭遇しました。

protocol GodsWill           {          func conforms() }
extension GodsWill          {          func conforms() { print("Everything conforms to God's Will") } }
class TheUniverse: GodsWill {  }
class Life: TheUniverse     {          func conforms() { print("Life conforms to God's Will") } }
class Humans: Life          { override func conforms() { print("Though created by God, Humans sometimes think they know better") } }

let universe = TheUniverse()
let life = Life()
let humans = Humans()

universe.conforms()
life.conforms()
humans.conforms()
print("-------------------------")
let array:[GodsWill] = [universe,life,humans]
for item in array { item.conforms() }

ここで、TheUniverse には conforms() のカスタム実装がないことに注意してください。出力は次のとおりです。

Everything conforms to God's Will
Life conforms to God's Will
Though created by God, Humans sometimes think they know better
-------------------------
Everything conforms to God's Will
Everything conforms to God's Will
Everything conforms to God's Will

最初の 3 つの print() 行はまさに私が期待し、望んでいるものですが、最後の 3 行は本当に困惑します。conforms() はプロトコル要件であるため、上の 3 行と同じでなければなりません。しかし、conforms() がプロトコル拡張に実装されているが、プロトコル要件としてリストされていないかのように動作します。これについては、The Swift Programming Language リファレンス マニュアルには何もありません。この WWDC のビデオはちょうど 30:40 で、私の主張を証明しています。

それで、私は何か間違ったことをしたのですか、機能を誤解したのですか、それとも Swift 3 でバグを見つけましたか?

4

1 に答える 1

1

さらに調査したところ、これは WWDC ビデオとはまったく関係がないと思います。

ユニバースはメソッドを定義しないため、ユニバースconformsを呼び出すconformsと「すべて...」が出力されます。

人生はconforms方法を定義します。conformsただし、拡張のために既に実装されているユニバースから継承するため、このconformsメソッドはプロトコルでは実際には必要ありません。したがって、プロトコルの種類はクラスのconformsメソッドを無視します。Life言い換えれば、次の出力でわかるように、のメソッドはプロトコル拡張のメソッドをconformsシャドーLifeイングしています。conforms

let a: TheUniverse = Life()
a.conforms()
Life().conforms()
// output:
// Everything conforms to God's Will
// Life conforms to God's Will

人間には別のconforms方法があります。今回は で定義しoverrideます。ただし、これはプロトコル拡張overrideのメソッドをオーバーライドしません。conforms代わりに、の直接のスーパークラスであるのconformsメソッドをオーバーライドします。これは、次のコードの出力によって証明できます。LifeHumans

let a: Life = Humans()
a.conforms()
// output:
// Though created by God, Humans sometimes think they know better

したがって、プロトコル拡張のメソッドはオーバーライドされません。したがって、いくつかのオブジェクトを作成して [GodsWill] に入れると、シャドウイングは効果がないため、プロトコル拡張メソッドが呼び出されます。

于 2016-10-23T07:35:57.167 に答える