Я намагаюся створити загальну функцію, яка приймає закриття як параметр. У мене, проте, виникає проблема, тому для усунення проблеми я створив наступний код, який можна запустити на ігровому майданчику.
class BaseClass {
init(message: String) {
println("Base class says: " + message)
}
func getMyName() -> String {
return "BaseClass"
}
}
class SubClass: BaseClass {
override init(message: String) {
println("Subclass says: " + message)
super.init(message: message)
}
override func getMyName() -> String {
return "SubClass"
}
func specialAbility() {
println("only I can do this!")
}
}
func makeInstance<T: BaseClass>(callback: (T -> Void)?) {
callback?(T(message: "hello"))
}
makeInstance() {
(instance: SubClass) in
println("makeInstance1 built a " + instance.getMyName())
println("I think it is a (_stdlib_getDemangledTypeName(instance))")
//instance.specialAbility() - uncommenting this throws EXC_BAD_ACCESS at runtime
}
makeInstance() {
(instance: BaseClass) in
println("makeInstance2 built a " + instance.getMyName())
println("I think it is a (_stdlib_getDemangledTypeName(instance))")
}
Цей код дає такий вихід:
Base class says: hello
makeInstance1 built a BaseClass
I think it is a __lldb_expr_89.SubClass
Base class says: hello
makeInstance2 built a BaseClass
I think it is a __lldb_expr_89.BaseClass
Swift не дозволяє чітко вказати типу виклику функції (наприклад, makeInstance), тому я очікую, що компілятор виведе його з типу закриття в виклику. Здається, щоразу створює екземпляр BaseClass. Ініціалізатор SubClass не викликається, і його члени з'являються бути таким, як BaseClass.
Смію сказати, що це здається помилкою у Свіфта; якщо виспробуйте отримати доступ до члена SubClass під час першого закриття, у компілятора немає проблем з цим, але під час виконання викид викидається (див. мій коментар у коді).
Будь-які ідеї, як я можу обійти це? Якщо це не зрозуміло, я б хотів створити підклас BaseClass, коли закриття очікує його.
Відповіді:
2 для відповіді № 1Я фактично просто змінив ваші ініціалізатори на такі, як це потрібно:
class BaseClass {
required init(message: String) {
println("Base class says: " + message)
}
func getMyName() -> String {
return "BaseClass"
}
}
class SubClass: BaseClass {
required init(message: String) {
println("Subclass says: " + message)
super.init(message: message)
}
...
}
і це працює без проблем