Ограниченные typealias не использует ограничения - PullRequest
0 голосов
/ 06 февраля 2019

Это работает:

protocol Walkable {
    init()
}

class Animal {
    init(someProperty: Int) {}
}

class WalkableAnimal: Animal, Walkable {
    required init() {
        super.init(someProperty: 0)
    }
}

class Person {
    init() {
        InitializeAWalkableAnimal(walkableAnimal: WalkableAnimal.self)
    }

    func InitializeAWalkableAnimal<T: Animal>(walkableAnimal: T.Type) where T: Walkable {
        let animal = walkableAnimal.init()
    }
}

Однако я хочу полностью отказаться от подкласса WalkableAnimal.Я просто хочу создать Cat class, который наследуется от Animal и соответствует протоколу Walkable.Кроме того, я не могу передать Cat напрямую в качестве параметра, потому что типы являются динамическими.Я ожидаю, что что-то вроде этого должно работать:

protocol Walkable {
    init()
}

class Animal {
    init(someProperty: Int) {}
}

class Cat: Animal, Walkable {
    required init() {
        super.init(someProperty: 0)
    }
}

class Dog: Animal, Walkable {
    required init() {
        super.init(someProperty: 1)
    }
}

typealias AnyWalkableAnimal = (Animal & Walkable).Type

class Person {
    init(anyWalkableAnimal: AnyWalkableAnimal) {
        // ERROR
        InitializeAWalkableAnimal(walkableAnimal: anyWalkableAnimal.self)
    }

    func InitializeAWalkableAnimal<T: Animal>(walkableAnimal: T.Type) where T: Walkable {
        let animal = walkableAnimal.init()
    }
}

class PersonCaller {
    init() {
        Person(anyWalkableAnimal: Cat.self)
        Person(anyWalkableAnimal: Dog.self)
    }
}

Ошибка:

Метод экземпляра 'InitializeAWalkableAnimal (walkableAnimal :)' требует, чтобы 'Animal' соответствовал 'Walkable'

Это нонсенс, поскольку typealias не допускает типы, которые не Walkables, верно?Почему компилятор не счастлив?Можно ли как-нибудь обойти любой тип, который соответствует Animal и Walkable?Почему typealias не работает?typealias прямо указывает, что тип, который он принимает, должен быть Animal и Walkable.Это работает наоборот (как и ожидалось): когда я пытаюсь передать Animal, который не соответствует Walkable, инициализатор выдает ошибку компиляции.

Я занимаюсь разработкой Swift Development Toolchain 25 декабря 2018 года, если это что-то изменит.

1 Ответ

0 голосов
/ 06 февраля 2019

Я не понимаю, почему InitializeAWalkableAnimal вообще должно быть универсальным.

protocol Walkable {
    init()
}

class Animal {
    init(someProperty: Int) { }
}

class Cat: Animal, Walkable {
    required init() { super.init(someProperty: 0) }
}

class Dog: Animal, Walkable {
    required init() { super.init(someProperty: 1) }
}

typealias Pet = Animal & Walkable
typealias PetType = Pet.Type

class Person {
    init(petType: PetType) {
        initPet(petType: petType)
    }

    func initPet(petType: PetType) {
        let pet = petType.init()
        print("I got a pet: \(pet)")
    }
}

class PersonCaller {
    init() {
        Person(petType: Cat.self)
        Person(petType: Dog.self)
    }
}

_ = PersonCaller()

Вывод:

I got a pet: __lldb_expr_8.Cat
I got a pet: __lldb_expr_8.Dog
...