约束类型别名不使用约束

时间:2019-02-06 19:15:36

标签: swift generics type-alias

这有效:

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 :)'需要   “动物”符合“可行走”

这是胡说八道,因为typealias不允许使用不是Walkables正确的类型?为什么编译器不满意?我是否可以通过任何方式同时符合AnimalWalkable的任何类型? typealias为什么不起作用? typealias明确提到其采用的类型必须是AnimalWalkable。它以相反的方式工作(按预期方式):当我尝试传递不符合Animal的{​​{1}}时,初始化程序会产生编译错误。

如果有任何不同,我将在Swift开发工具链上进行开发,时间为2018年12月25日。

1 个答案:

答案 0 :(得分:2)

我完全不明白为什么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