Изменение метода generate() для подкласса класса, соответствующего "SequenceType"
Допустим, у меня есть общий класс Parent<P>
, что соответствует SequenceType
протокол, реализуя generate()
метод:
class Parent<P> {
//...
}
extension Parent: SequenceType {
func generate() -> GeneratorOf<[P]> {
//...
return GeneratorOf<[P]> {
//return the next element, or nil to stop
}
}
Теперь generate()
метод явно не просто возвращает элементы типа P
, но [P]
,
Теперь давайте реализуем подкласс Child<C>
:
class Child<C>: Parent<C> {
//...
}
Child
также должен соответствовать SequenceType
, но не должен возвращать элементы типа [C]
, скорее C
,
По логике вещей я бы попытался реализовать собственный generate()
метод:
extension Child: SequenceType {
func generate() -> GeneratorOf<C> {
//...
return GeneratorOf<C> {
//return the next element, or nil to stop
}
}
Это не работает, хотя, и Swift выдает ошибку:
<stdin>: error: type 'Child<C>' does not conform to protocol '_Sequence_Type'
extension Child: SequenceType {
^
Swift._Sequence_Type: note: multiple matching functions named 'generate()' with type '() -> Child<C>.Generator'
func generate() -> Generator
^
<stdin>: note: candidate exactly matches [with Generator = GeneratorOf<C>]
func generate() -> GeneratorOf<C> {
^
<stdin>: note: candidate exactly matches [with Generator = GeneratorOf<[C]>]
func generate() -> GeneratorOf<[P]> {
^
<stdin>: error: type 'Child<C>' does not conform to protocol 'SequenceType'
extension Child: SequenceType {
^
Swift.SequenceType: note: multiple matching functions named 'generate()' with type '() -> Child<C>.Generator'
func generate() -> Generator
^
<stdin>: note: candidate exactly matches [with Generator = GeneratorOf<C>]
func generate() -> GeneratorOf<C> {
^
<stdin>: note: candidate exactly matches [with Generator = GeneratorOf<[C]>]
func generate() -> GeneratorOf<[P]> {
В чем здесь проблема, и как я могу это исправить?
Обновление № 1:
Таким образом, проблема, кажется, решена путем применения подхода @rintaro, заключающегося только в определении typealias
за Generator
в Child
класс
Но, как обсуждалось в комментариях @AirspeedVelocity и @NateCook, это не очень жизнеспособный подход, потому что Child
класс также может быть подклассом.
Также было указано, что можно создать свойство экземпляра (которое я предполагаювычисленным), возвращающее последовательность нужных элементов:
class Parent<P> {
var asSequence: [[P]] {
//some kind of getter
}
//...
}
class Child<C>: Parent<C> {
override var asSequence: [C] {
//some kind of getter
}
//...
}
Экземпляры могут быть использованы в for-in-loop:
for element in someParent.asSequence {
//element is of type [P]
}
for element in someChild.asSequence {
//element is of type C
}
Это был бы "лучший" подход?
Обновление № 1.1:
Как подсказал @MichaelWelch, имена свойств (asSequence
) может привести к путанице в этом случае, поскольку они возвращают разные типы.
Это кажется уместным, но зависит от ситуации. Но в целом двусмысленности следует избегать.
1 ответ
Кажется, ты можешь. Явные typealias для Generator
только в Child
сделал трюк. Тем не менее, я также думаю, что вы не должны так делать...
class Parent<P> {
var _src:[[P]] = []
}
extension Parent: SequenceType {
func generate() -> GeneratorOf<[P]> {
var g = _src.generate()
return GeneratorOf<[P]> {
return g.next()
}
}
}
class Child<C>: Parent<C> {
var _ary:[C] = []
}
extension Child: SequenceType {
typealias Generator = GeneratorOf<C> // <-- HERE
func generate() -> GeneratorOf<C> {
var g = _ary.generate()
return GeneratorOf<C> {
return g.next()
}
}
}