Подтвердить что ты не робот

Как я могу вернуть 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()

Спасибо

4b9b3361

Ответ 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.