Понимание «Использование необъявленного типа» в унаследованном классе generi c - PullRequest
0 голосов
/ 30 марта 2020

Я только что наткнулся на этого любопытного повара ie и не могу понять, удивляюсь ли я тому, что это работает не так, как ожидалось, или что я впервые вижу это в прошлом пять лет, используя Swift каждый день.

Теперь я ожидал, что тип Bar будет доступен с Baz, но это не так:

class Foo<Bar> {
    func bar() -> Bar? { nil }
}
class Baz: Foo<String> {
    override func bar() -> Bar? { nil } // ? Use of undeclared type 'Bar'…
}

Это легко решается с помощью typealias:

class Foo<Bar> {
    typealias Bar = Bar // This just feels so wrong…
    func bar() -> Bar? { nil }
}
class Baz: Foo<String> {
    override func bar() -> Bar? { nil } // ? That's it…
}

Мои вопросы: это упоминается или объясняется где-нибудь в официальных документах? Какая польза от сокрытия Bar от наследования классов?

Одна из причин того, что это редкий случай, возможно, заключается в том, что мы часто передаем тип c generic:

class Foo<Bar> {
    func bar() -> Bar? { nil }
}
class Baz<Bar>: Foo<Bar> {
    override func bar() -> Bar? { nil } // ? No problems…
}

И используйте протоколы с associatedtype, который выполняет ту же работу, что и typealias выше:

protocol P {
    associatedtype Bar
}
class Foo<Bar>: P {
    func bar() -> Bar? { nil }
}
class Baz: Foo<String> {
    override func bar() -> Bar? { nil } // ? All good…
}

PS Я не спрашиваю, как это исправить. Я хочу знать, если текущее поведение упоминается где-либо в официальной документации или, в противном случае, если есть заслуживающая доверия статья, объясняющая причины, почему это работает так, как работает.

1 Ответ

0 голосов
/ 30 марта 2020

Foo<Bar> Bar - это просто typealias вашего типа 'generi c' (я имею в виду, какой тип вы хотите Int, Double et c.). Так что если вы дадите String Foo, как (Foo<String>), то теперь Bar псевдоним String. И псевдоним Bar распознает только из Foo.

class Foo<Bar> { 
    func bar() -> Bar? { return nil }
}

Неправильно

class Baz: Foo<String> {
    override func bar() -> Bar? { return nil } // `Bar` is `String` now so you should use `String?` in your return type
}

Исправлено

class Baz: Foo<String> {
    override func bar() -> String? { return nil }
}

БОНУС

hackingwithswift статья о Swift Generics

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...