Как я могу вернуть instancetype в Swift
Я хочу сделать расширение какого-либо класса, чтобы вернуть объект типа времени выполнения
например, я создаю extenstion класса A
extension A {
class func niceObject() -> XXXXX { // in objective-c is instancetype
return ....
}
}
Итак, кто-нибудь знает, есть ли ключевое слово instancetype в Swift или не заменять xxxxx
, и я могу вызвать эту функцию в подклассе A без ручного броска
var b: B = B.niceObject()
Спасибо
Ответы
Ответ 1
Вы можете это сделать. Код детской площадки ниже. Это self(), что niceObject() должен вернуться. Кроме того, вы должны иметь required
init в базовом классе.
class A {
required init() {
}
func whatClassAmI() -> String {
return "Class A"
}
}
class B: A {
required init() {
super.init()
}
override func whatClassAmI() -> String {
return "Class B"
}
}
let a = A()
let sa = a.whatClassAmI() // "Class A", of course
let b = B()
let sb = b.whatClassAmI() // "Class B", of course
extension A {
class func niceObject() -> Self {
return self.init()
}
}
let aa = A.niceObject()
let saa = aa.whatClassAmI() // "Class A"
let bb = B.niceObject()
let sbb = bb.whatClassAmI() // "Class B", as required
Ответ 2
Существует ключевое слово Self
, которое разрешено в двух местах - в протоколах (см. ответ Jean-Philippe Pellet) и в результате методов class
:
extension A {
class func niceObject() -> Self? {
return nil
}
}
К сожалению, это не поможет, потому что следующее недопустимо
extension A {
class func niceObject() -> Self? {
//A can't be converted to Self
return A()
}
}
Ошибка вызвана тем фактом, что при наследовании от A
class B : A {
}
затем
var b = B.niceObject()
действительно вернет экземпляр A
, который не может быть конвертирован в Self
(Self
is B
)
@Grimxn нашел правильное решение (См. его ответ):
Вы должны добавить требуемый инициализатор в базовый класс, например.
class A {
@required init() {
}
}
а затем вы можете вызвать инициализатор, используя self()
extension A {
class func niceObject() -> Self {
return self()
}
}
Ответ 3
По крайней мере, в прокотолях вы можете использовать Self
. Это представляет собой фактический тип Self
. Не уверен в расширениях, хотя...
Например, см. определение Equatable
:
protocol Equatable {
func ==(lhs: Self, rhs: Self) -> Bool
}
Ответ 4
Когда вы используете Swift API из Objective-C, компилятор обычно выполняет прямой перевод. Например, Swift API func playSong(name: String)
импортируется как - (void)playSong:(NSString *)name
в Objective-C.
Однако есть одно исключение: когда вы используете Swift initializer в Objective-C, компилятор добавляет текст "initWith
" к началу метода и правильно капитализирует первый символ в исходном инициализаторе.
Например, этот инициализатор Swift init (songName: String, artist: String)
импортируется как - (instancetype)initWithSongName:(NSString *)songName artist:(NSString *)artist
в Objective-C.