Полиморфизм с унаследованными дженериками приводит к плохому доступу в swift

У меня есть два класса, которые наследуются от общего класса.

class Parser<I: CollectionType, T> {
    func parse(ts: I) -> [(T, I)] { return [] }

    func parse_all(ts: I) -> [(T, I)] {
        return parse(ts).filter { isEmpty($0.1) }
    }
}

class CharParser<I: CollectionType, T> : Parser<[Character], Character> {
    let c: Character

    init(c: Character) { self.c = c }

    override func parse(ts: [Character]) -> [(Character, [Character])] {
        println(ts)
        return ts[0] == c ? [(ts[0], Array(ts[1..<ts.count]))] : []
    }
}

class AltParser<I: CollectionType, T> : Parser<I, T> {
    let p: Parser<I, T>
    let q: Parser<I, T>

    init(p: Parser<I, T>, q: Parser<I,T>) {
        self.p = p
        self.q = q
    }

    override func parse(ts: I) -> [(T, I)] {
        println(ts)
        return p.parse(ts) + q.parse(ts)
    }
}

class SeqParser<I: CollectionType, T, S>: Parser<I, (T, S)> {
    let p: Parser<I, T>, q: Parser<I,S>

    init(p: Parser<I, T>, q: Parser<I,S>) { self.p = p; self.q = q }

    override func parse(ts: I) -> [((T, S), I)] {
        var acc = [((T, S), I)]()
        for (head1, tail1) in p.parse(ts) {
            for (head2, tail2) in q.parse(tail1) {
                acc += [((head1, head2), tail2)]
            }
        }
        return acc
    }
}

Вызов

let x = CharParser<[Character], Character>(c: "a")
x.parse(Array("a"))

работает нормально, однако попытка вызвать его через AltParser вызывает EXC_BAD_ACCESS

let x2 = CharParser<[Character], Character>(c: "b")
let y = AltParser(p: x, q: x2)
let z = y.parse(Array("a"))

Это ошибка компилятора или я неправильно понимаю дженерики?


person HaniKazmi    schedule 10.11.2014    source источник
comment
Вызов let x = CharParser<[Character], Character>(c: "a"); x.parse("a") работает нормально Правда? На моей машине не компилируется. Какую версию Xcode вы используете?   -  person matt    schedule 10.11.2014
comment
@matt Извините, это должно было быть x.parse(Array("a"))   -  person HaniKazmi    schedule 10.11.2014


Ответы (1)


Хорошо, мне не удалось полностью показать, что вы не можете этого сделать, теперь я попытаюсь показать, что вы можете это сделать. Вот сильно упрощенная версия вашего кода, который, как мне кажется, работает (по крайней мере, он компилируется и не дает сбоев):

class Parser<T> {
    func parse(ts:[T]) -> [(T, [T])] { println ("super"); return []}
}
class StringParser<T> : Parser<String> {
    let c : String
    init(c: String) { self.c=c }
    override func parse(ts:[String]) -> [(String, [String])] {
        println ("sub")
        return ts[0] == c ? [(ts[0], Array(ts[1..<ts.count]))] : []
    }
}
class AltParser<T> : Parser<T> {
    let p : Parser<T>
    init(p:Parser<T>) {
        self.p = p
    }
    override func parse(ts:[T]) -> [(T, [T])] {
        return p.parse(ts)
    }
}
func test() {
    let x = StringParser<Character>(c:"a")
    x.parse(["a"])
    let z = AltParser(p:x)
    println(z.parse(["a"]))
}

Я исключил все, что показалось лишним в примере. Я превратил символ в строку, потому что я нахожу символ запутанным. Я удалил parse_all и второе свойство q, потому что вы их ни для чего не использовали. Самое главное, я удалил весь CollectionType из универсального и везде заменил его явным массивом; это было потому, что CollectionType доставлял мне проблемы при компиляции. Я был разочарован, в частности, когда у меня все еще был CollectionType в универсальном, из-за невозможности найти способ указать, что это коллекция T; мне казалось каким-то важным, чтобы это было ясно. Это одна из причин, по которой я удалил его и заменил явным массивом T. Но, возможно, я наткнулся на что-то полезное, потому что код теперь работает.

Иди и разбери его...!

person matt    schedule 12.11.2014
comment
Спасибо за это, помогли мне добиться некоторого прогресса. Оказывается, проблема не в CollectionType, а в попытке специализироваться на двух дженериках. К сожалению, мне нужны оба дженерика, поэтому похоже, что я застрял, пока Apple не исправит эту ошибку. Я обновил свой пост, чтобы показать, почему мне нужно как минимум два дженерика, любая помощь в этой работе будет оценена по достоинству. - person HaniKazmi; 01.12.2014