简体   繁体   English

在 Swift 中返回基于协议的具体类型

[英]Returning the Concrete Type Based on Protocol in Swift

I have following code:我有以下代码:

protocol Vehicle {
    func start()
}

class Car: Vehicle {
    func start() {
        print("Start car")
    }
}

class MotorCycle: Vehicle {
    func start() {
        print("Start MotorCycle")
    }
}

let vehicles: [Vehicle] = [Car(), MotorCycle()]

func get<T: Vehicle>() -> some Vehicle {
    let result = vehicles.first {
        $0 === T.self
    }
    return result!
}

// so I should be able to do this! 
let car = get<Car>().start() 

Inside the get function I want to go iterate through vehicles and return the concrete type of the Vehicle, which is either Car or MotorCycle .get函数中,我想遍历车辆并返回 Vehicle 的具体类型,即CarMotorCycle Finally, I want to call start on the returned type.最后,我想对返回的类型调用start How can I achieve it?我怎样才能实现它?

在此处输入图片说明

This is how get should be written: get应该这样写:

func get<T: Vehicle>(_ type: T.Type) -> T? {
    vehicles.first(where: { $0 is T }) as? T
}
  • There might not be any T s in vehicles , so we should return an optional T . vehicles可能没有任何T ,所以我们应该返回一个可选的T
  • For the implementation, you should use is to check the type in the first(where:) closure.对于实现,您应该使用isfirst(where:)闭包中检查类型。 Then, cast to T .然后,转换为T
  • You can't directly pass type arguments like <Car> to a function in Swift.你不能直接将像<Car>这样的类型参数传递给 Swift 中的函数。 Type arguments must always be inferred.必须始终推断类型参数。 So I used a formal parameter type to help Swift infer what T is.所以我使用了一个形参type来帮助 Swift 推断T是什么。

Caller:呼叫者:

get(Car.self)?.start()

You can not compare an instance value with a type like this: $0 === T.self .您不能将实例值与这样的类型进行比较: $0 === T.self You can use $0 is T instead.您可以使用$0 is T代替。

And, when calling a generic function, you cannot explicitly specialize a generic function.并且,在调用泛型函数时,您不能显式特化泛型函数。 The type has to be inferred, like @Sweeper said.必须推断类型,就像@Sweeper 所说的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM