[英]Generic class of generic class with one argument/parameter
我的数据结构存在语法问题。 更糟糕的是我不能详细谈论它。 我受雇的公司在公共交通部门运营,我在保密协议下,如果我发布任何太具体的内容,老板会杀了我。 我希望你明白!
我有这个完美的例子。 根本没有不一致;)好吧,有。 然而,我相信你们中的大多数人都足够聪明,可以得到这里重要的东西。
基本结构:
class Propulsion {
var horsePower: Double
init(horsePower: Double) {
self.horsePower = horsePower
}
static let pedes = Propulsion(horsePower: 0.2)
}
class Motor: Propulsion {
var range: Double
init(range: Double, horsePower: Double) {
self.range = range
super.init(horsePower: horsePower)
}
static let otto = Motor(range: 1000, horsePower: 100)
static let electric = Motor(range: 400, horsePower: 200)
}
class Vehicle<P: Propulsion> {
var propulsion: P
init(propulsion: P) {
self.propulsion = propulsion
}
}
class Bicycle<P: Propulsion>: Vehicle<P> {
var hasFrontSuspension: Bool
init(hasFrontSuspension: Bool, propulsion: P) {
self.hasFrontSuspension = hasFrontSuspension
super.init(propulsion: propulsion)
}
}
class Car<P: Propulsion>: Vehicle<P> {
func rangePerHorsePower() -> Double where P: Motor {
propulsion.range / propulsion.horsePower
}
}
现在我想申报一个汽车停车位。 像这样:
var carParkingSpot: ParkingSpot<Car<Motor>>
对于 class ParkingSpot
,我有一些像这样的 class:
class ParkingSpot<V: Vehicle<P>> where P: Propulsion {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
从最后一点我得到了一堆
在 scope 中找不到类型“P”
这个也不起作用:
class ParkingSpot<V: Vehicle<P: Propulsion>>
期望“>”来完成通用参数列表
这个实现虽然有效:
class ParkingSpot<V: Vehicle<P>, P: Propulsion> {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
但是我不想复制Motor
位:
var carParkingSpot: ParkingSpot<Car<Motor>, Motor>
如何仅使用一个通用参数来完成此操作?
您可以使用“面向协议”的方法:
protocol PropulsionP {
var horsePower: Double { get }
}
protocol MotorP: PropulsionP {
var range: Double { get }
}
struct MotorS: MotorP {
var range: Double
var horsePower: Double
init(range: Double, horsePower: Double) {
self.range = range
self.horsePower = horsePower
}
}
protocol VehicleP {
associatedtype P: PropulsionP
var propulsion: P { get }
}
struct BicycleS<Prop: PropulsionP>: VehicleP {
let hasFrontSuspension: Bool
var propulsion: Prop
init(
hasFrontSuspension: Bool,
propulsion: Prop
) {
self.hasFrontSuspension = hasFrontSuspension
self.propulsion = propulsion
}
}
struct CarS<Prop: PropulsionP>: VehicleP {
var propulsion: Prop
func rangePerHorsePower() -> Double where P: MotorP {
propulsion.range / propulsion.horsePower
}
}
struct ParkingSpotS<V: VehicleP> {
var vehicle: V
init(vehicle: V) {
self.vehicle = vehicle
}
func taxForRange() -> Double where V.P: MotorP {
vehicle.propulsion.range * 50
}
}
var carParkingSpot: ParkingSpotS<CarS<MotorS>>
无双MotorS
钻头。 Quod erat demonstrandum。
我使用了有点不寻常的命名来强调这一点。
(需要进行一些编辑,在我实际需要MotorP
的地方输入错误的Motor
)
更新
我开着我喜欢的车在路上试了一下:
var carParkingSpot: ParkingSpotS<CarS<MotorS>> = .init(
vehicle: .init(
propulsion: .init(
range: 760,
horsePower: 240
)
)
)
print(carParkingSpot.taxForRange())
38000.0
或者,您可以使用此初始化程序:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: MotorS(
range: 760,
horsePower: 240
)
)
)
更新
现在假设您正在使用第三方库,它已经提供了一个很好的电机实现。
您需要做的是为他们给定的 class 或符合您的协议MotorP
的结构TheirMotor
实施扩展:
import FancyMotors
extension TheirMotor: MotorP {
let range: Double {
// calculate `range` in terms of the
// given API of `TheirMotor`:
...
return range
}
}
然后,您可以像下面这样使用它:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: TheirMotor(
distance: 760,
power: 240
)
)
)
请注意,您使用TheirMotor
并且需要使用适当的初始化程序来创建它。
这似乎有效:
class ParkingSpot<V: Vehicle<Propulsion>>
{
var vehicle: V
init(vehicle: V)
{
self.vehicle = vehicle
}
func taxForEngineeNoise() -> Double
{
switch vehicle.propulsion
{
case is Motor:
return vehicle.propulsion.horsePower * 50
default:
...
}
}
func taxForRange() -> Double
{
if let motor = vehicle.propulsion as? Motor
{
return motor.range * 50
}
else
{
...
}
}
}
或者,也许可以隐藏重复项?
typealias ParkingSpotX = ParkingSpot<Car<Motor>, Motor>
var parkingSpot: ParkingSpotX
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.