Вот сделка. Я сталкивался с таким поведением в моем программировании реализации, и это действительно озадачило меня. Я пытаюсь выяснить, почему это происходит, поэтому я могу объяснить это в будущем.
Я вставлю довольно сложную (но минимальную) площадку через минуту, но я хотел обрисовать проблему , во-первых.
Проблема в том, что, если я определяю класс (не структуру) как соответствующий протоколу с реализацией по умолчанию, а затем переопределяю это путем реализации определенного метода, реализация протокола по умолчанию продолжает выполняться , даже когда я ожидал, что вторичная реализация будет выполнена, а иерархии наследования будут игнорироваться.
Ниже у меня есть игровая площадка (последний Xcode) и полученная распечатка.
ЧТО Я ОЖИДАЮ
Все должно следовать примеру, установленному прямым вызовом метода (1). Это включает в себя пару откатов к значениям по умолчанию протокола.
ЧТО НА СЛУЧАЕ ПРОИСХОДИТ
Реализация по умолчанию в протоколах (из которой происходят классы / которой соответствуют классы) ) продолжает выполняться.
Наиболее удивительными являются (6) - (8).
(2) - (4) также немного странны, так как D и E (и Q и R) печататься правильно, но ни один из других не делает.
Кто-нибудь имеет какие-либо идеи, почему я могу получить это поведение?
ИЕРАРХИЯ КАРТА
игровая площадка:
// MARK: - Test Functions
// Argument is Class A
func printValueFromClassA(_ inValueAsClassA: A) {
inValueAsClassA.printValue()
}
// Argument is Class H
func printValueFromClassH(_ inValueAsClassH: H) {
inValueAsClassH.printValue()
}
// Argument is Class J
func printValueFromClassJ(_ inValueAsClassJ: J) {
inValueAsClassJ.printValue()
}
// Argument is Class D
func printValueFromClassD(_ inValueAsClassD: D) {
inValueAsClassD.printValue()
}
// Argument is the Root protocol
func printValueFromProtocolA(_ inValueAsProtocolA: PA) {
inValueAsProtocolA.printValue()
}
// Argument is the first derived protocol
func printValueFromProtocolB(_ inValueAsProtocolB: PB) {
inValueAsProtocolB.printValue()
}
// Argument is the second derived protocol
func printValueFromProtocolC(_ inValueAsProtocolC: PC) {
inValueAsProtocolC.printValue()
}
// MARK: - Protocols
// Root protocol: Defines the method
protocol PA {
func printValue()
}
// Root protocol default implementation
extension PA {
func printValue() { print("\t\tProtocol A") }
}
// Derived protocol: Depends on Root protocol default
protocol PB: PA { }
// Derived protocol: defines a new default implementation
protocol PC: PB { }
// Deived protocol default implementation
extension PC {
func printValue() { print("\t\tProtocol C") }
}
// MARK: - Classes
// Direct conformance to PA; relying on the default implementation of the conforming method
class A: PA { }
// Derives from A, but implements the conforming method
class B: A {
func printValue() { print("\t\tClass B") }
}
// Derives from B, and overrides the conforming method
class C: B {
override func printValue() { print("\t\tClass C") }
}
// Direct conformance to PB (which is based on PA), and implements the conforming method
class D: PB {
func printValue() { print("\t\tClass D") }
}
// Derives from D, and overrides the conforming method
class E: D {
override func printValue() { print("\t\tClass E") }
}
// Direct conformance to PA, but defines the conforming method
class F: A {
func printValue() { print("\t\tClass F") }
}
// Derives from C, and overrides the conforming method (second override)
class G: C {
override func printValue() { print("\t\tClass G") }
}
// Direct conformance to PB, but relies on the default implementation of the conforming method
class H: PB { }
// Derives from H, but implements the conforming method.
class I: H {
func printValue() { print("\t\tClass I") }
}
// Direct conformance to the second derived protocol, and relies on that protocol's default implementation
class J: PC { }
// Derived from J, but implements the conforming method
class K: J {
func printValue() { print("\t\tClass K") }
}
// Derived from J, and overrides the method
class L: K {
override func printValue() { print("\t\tClass L") }
}
// Derived from F, and overrides the method
class M: F {
override func printValue() { print("\t\tClass M") }
}
// Derived from I, and overrides the method
class N: I {
override func printValue() { print("\t\tClass N") }
}
// Derived from N, and overrides the method
class O: N {
override func printValue() { print("\t\tClass O") }
}
// Derived from L, and overrides the method
class P: L {
override func printValue() { print("\t\tClass P") }
}
// Direct conformance to the second derived protocol, but implements the conforming method
class Q: PC {
func printValue() { print("\t\tClass Q") }
}
// Derived from Q, and overrides the method
class R: Q {
override func printValue() { print("\t\tClass R") }
}
// MARK: - Testing
// MARK: instance definitions
let instanceOfA = A()
let instanceOfB = B()
let instanceOfC = C()
let instanceOfD = D()
let instanceOfE = E()
let instanceOfF = F()
let instanceOfG = G()
let instanceOfH = H()
let instanceOfI = I()
let instanceOfJ = J()
let instanceOfK = K()
let instanceOfL = L()
let instanceOfM = M()
let instanceOfN = N()
let instanceOfO = O()
let instanceOfP = P()
let instanceOfQ = Q()
let instanceOfR = R()
// MARK: Directly calling the instance methods
print("1) Direct Method Call:")
print("\tClass A:")
instanceOfA.printValue() // "Protocol A"
print("\tClass B:")
instanceOfB.printValue() // "Class B"
print("\tClass C:")
instanceOfC.printValue() // "Class C"
print("\tClass D:")
instanceOfD.printValue() // "Class D"
print("\tClass E:")
instanceOfE.printValue() // "Class E"
print("\tClass F:")
instanceOfF.printValue() // "Class F"
print("\tClass G:")
instanceOfG.printValue() // "Class G"
print("\tClass H:")
instanceOfH.printValue() // "Protocol A"
print("\tClass I:")
instanceOfI.printValue() // "Class I"
print("\tClass J:")
instanceOfJ.printValue() // "Protocol C"
print("\tClass K:")
instanceOfK.printValue() // "Class K"
print("\tClass L:")
instanceOfL.printValue() // "Class L"
print("\tClass M:")
instanceOfM.printValue() // "Class M"
print("\tClass N:")
instanceOfN.printValue() // "Class N"
print("\tClass O:")
instanceOfO.printValue() // "Class O"
print("\tClass P:")
instanceOfP.printValue() // "Class P"
print("\tClass Q:")
instanceOfQ.printValue() // "Class Q"
print("\tClass R:")
instanceOfR.printValue() // "Class R"
// MARK: Calling via a function that requires the argument be the Root protocol
print("\n2) printValueFromProtocolA(_: PA):")
print("\tClass A:")
printValueFromProtocolA(instanceOfA) // "Protocol A"
print("\tClass B:")
printValueFromProtocolA(instanceOfB) // "Protocol A"
print("\tClass C:")
printValueFromProtocolA(instanceOfC) // "Protocol A"
print("\tClass D:")
printValueFromProtocolA(instanceOfD) // "Class D"
print("\tClass E:")
printValueFromProtocolA(instanceOfE) // "Class E"
print("\tClass F:")
printValueFromProtocolA(instanceOfF) // "Protocol A"
print("\tClass G:")
printValueFromProtocolA(instanceOfG) // "Protocol A"
print("\tClass H:")
printValueFromProtocolA(instanceOfH) // "Protocol A"
print("\tClass I:")
printValueFromProtocolA(instanceOfI) // "Protocol A"
print("\tClass J:")
printValueFromProtocolA(instanceOfJ) // "Protocol C"
print("\tClass K:")
printValueFromProtocolA(instanceOfK) // "Protocol C"
print("\tClass L:")
printValueFromProtocolA(instanceOfL) // "Protocol C"
print("\tClass M:")
printValueFromProtocolA(instanceOfM) // "Protocol A"
print("\tClass N:")
printValueFromProtocolA(instanceOfN) // "Protocol A"
print("\tClass O:")
printValueFromProtocolA(instanceOfO) // "Protocol A"
print("\tClass P:")
printValueFromProtocolA(instanceOfP) // "Protocol A"
print("\tClass Q:")
printValueFromProtocolA(instanceOfQ) // "Class Q"
print("\tClass R:")
printValueFromProtocolA(instanceOfR) // "Class R"
// MARK: Calling via a function that requires the argument be the first Derived protocol
print("\n3) printValueFromProtocolB(_: PB):")
print("\tClass D:")
printValueFromProtocolB(instanceOfD) // "Class D"
print("\tClass E:")
printValueFromProtocolB(instanceOfE) // "Class E"
print("\tClass H:")
printValueFromProtocolB(instanceOfH) // "Protocol A"
print("\tClass I:")
printValueFromProtocolB(instanceOfI) // "Protocol A"
print("\tClass J:")
printValueFromProtocolB(instanceOfJ) // "Protocol C"
print("\tClass K:")
printValueFromProtocolB(instanceOfK) // "Protocol C"
print("\tClass L:")
printValueFromProtocolB(instanceOfL) // "Protocol C"
print("\tClass N:")
printValueFromProtocolB(instanceOfN) // "Protocol A"
print("\tClass O:")
printValueFromProtocolB(instanceOfO) // "Protocol A"
print("\tClass P:")
printValueFromProtocolB(instanceOfP) // "Protocol A"
print("\tClass Q:")
printValueFromProtocolB(instanceOfQ) // "Protocol A"
print("\tClass R:")
printValueFromProtocolB(instanceOfR) // "Protocol A"
// MARK: Calling via a function that requires the argument be the second Derived protocol
print("\n4) printValueFromProtocolC(_: PC):")
print("\tClass J:")
printValueFromProtocolC(instanceOfJ) // "Protocol C"
print("\tClass K:")
printValueFromProtocolC(instanceOfK) // "Protocol C"
print("\tClass L:")
printValueFromProtocolC(instanceOfL) // "Protocol C"
print("\tClass P:")
printValueFromProtocolC(instanceOfP) // "Protocol C"
print("\tClass Q:")
printValueFromProtocolC(instanceOfQ) // "Class Q"
print("\tClass R:")
printValueFromProtocolC(instanceOfR) // "Class R"
// MARK: Calling via a function that requires the argument be an instance or subclass of Class D
print("\n5) printValueFromClassD(_: D):")
print("\tClass D:")
printValueFromClassD(instanceOfD) // "Class D"
print("\tClass E:")
printValueFromClassD(instanceOfE) // "Class E"
// MARK: Calling via a function that requires the argument be an instance or subclass of Class A
print("\n6) printValueFromClassA(_: A):")
print("\tClass A:")
printValueFromClassA(instanceOfA) // "Protocol A"
print("\tClass B:")
printValueFromClassA(instanceOfB) // "Protocol A"
print("\tClass C:")
printValueFromClassA(instanceOfC) // "Protocol A"
print("\tClass G:")
printValueFromClassA(instanceOfG) // "Protocol A"
// MARK: Calling via a function that requires the argument be an instance or subclass of Class H
print("\n7) printValueFromClassH(_: H):")
print("\tClass H:")
printValueFromClassH(instanceOfH) // "Protocol A"
print("\tClass I:")
printValueFromClassH(instanceOfI) // "Protocol A"
print("\tClass N:")
printValueFromClassH(instanceOfN) // "Protocol A"
print("\tClass O:")
printValueFromClassH(instanceOfO) // "Protocol A"
// MARK: Calling via a function that requires the argument be an instance or subclass of Class J
print("\n8) printValueFromClassJ(_: J):")
print("\tClass J:")
printValueFromClassJ(instanceOfJ) // "Protocol C"
print("\tClass K:")
printValueFromClassJ(instanceOfK) // "Protocol C"
print("\tClass L:")
printValueFromClassJ(instanceOfL) // "Protocol C"
print("\tClass P:")
printValueFromClassJ(instanceOfP) // "Protocol C"
ПЕЧАТЬ:
1) Direct Method Call:
Class A:
Protocol A
Class B:
Class B
Class C:
Class C
Class D:
Class D
Class E:
Class E
Class F:
Class F
Class G:
Class G
Class H:
Protocol A
Class I:
Class I
Class J:
Protocol C
Class K:
Class K
Class L:
Class L
Class M:
Class M
Class N:
Class N
Class O:
Class O
Class P:
Class P
Class Q:
Class Q
Class R:
Class R
2) printValueFromProtocolA(_: PA):
Class A:
Protocol A
Class B:
Protocol A
Class C:
Protocol A
Class D:
Class D
Class E:
Class E
Class F:
Protocol A
Class G:
Protocol A
Class H:
Protocol A
Class I:
Protocol A
Class J:
Protocol C
Class K:
Protocol C
Class L:
Protocol C
Class M:
Protocol A
Class N:
Protocol A
Class O:
Protocol A
Class P:
Protocol C
Class Q:
Class Q
Class R:
Class R
3) printValueFromProtocolB(_: PB):
Class D:
Class D
Class E:
Class E
Class H:
Protocol A
Class I:
Protocol A
Class J:
Protocol C
Class K:
Protocol C
Class L:
Protocol C
Class N:
Protocol A
Class O:
Protocol A
Class P:
Protocol C
Class Q:
Class Q
Class R:
Class R
4) printValueFromProtocolC(_: PC):
Class J:
Protocol C
Class K:
Protocol C
Class L:
Protocol C
Class P:
Protocol C
Class Q:
Class Q
Class R:
Class R
5) printValueFromClassD(_: D):
Class D:
Class D
Class E:
Class E
6) printValueFromClassA(_: A):
Class A:
Protocol A
Class B:
Protocol A
Class C:
Protocol A
Class G:
Protocol A
7) printValueFromClassH(_: H):
Class H:
Protocol A
Class I:
Protocol A
Class N:
Protocol A
Class O:
Protocol A
8) printValueFromClassJ(_: J):
Class J:
Protocol C
Class K:
Protocol C
Class L:
Protocol C
Class P:
Protocol C