Ответ 1
Попробуйте следующее:
func someFunc<T:ProtocolWithAlias>() -> T
Я пытаюсь сделать следующее в Swift:
protocol ProtocolWithAlias {
typealias T
}
protocol AnotherProtocol {
func someFunc() -> ProtocolWithAlias
}
Но я получаю ошибку: Protocol 'ProtocolWithAlias' can only be used as a generic constraint because it has Self or associated type requirements
.
Можно ли сделать что-то подобное? Сообщение об ошибке (или, по крайней мере, часть "only be used as a generic constraint
" ), кажется, не имеет большого смысла для меня.
Я использую последнюю версию Xcode 6 beta 3.
Спасибо!
Попробуйте следующее:
func someFunc<T:ProtocolWithAlias>() -> T
Это можно реализовать, инвертируя элемент управления: вместо того, чтобы возвращать значение из someFunc, мы передаем потребителю, который может принимать любые типы, реализующие ProtocolWithAlias, и что-то делать с ним.
protocol ProtocolWithAlias {
typealias T
}
protocol ProtocolConsumer {
func consume<T: ProtocolWithAlias>(value: T)
}
protocol AnotherProtocol {
func someFunc(consumer: ProtocolConsumer)
}
Этот трюк известен как преобразование функции в стиль продолжения передачи (CPS). К сожалению, я не смог найти способ реализовать это без CPSing. Тип системы, который мы ищем, - это экзистенциальные типы (и этот поток имеет приятное объяснение), но я думаю, что Swift их не поддерживает (пока).
Почему другой ответ не правильный? Что говорит эта подпись:
func someFunc<T:ProtocolWithAlias>() -> T
заключается в том, что эта функция может возвращать значение типа T для любого типа, реализующего ProtocolWithAlias, который выбирает вызывающий, но мы хотели, чтобы он был выбран вызываемым.
Невозможно даже написать разумную реализацию этой функции. Давайте сделаем вид, что у меня есть реализация someFunc: я мог бы создать новый класс, реализующий ProtocolWithAlias, и попросить someFunc каким-то образом создать экземпляр этого класса:
class Uninhabited: ProtocolWithAlias {
typealias T = Int
init(nope: Uninhabited) {}
}
...
let impossible: Uninhabited = someFunc<Uninhabited>()