我的数据 struct 有这个语法问题.更糟糕的是,我不能详细谈论它.我受雇的公司经营公共交通部门,我在保密协议下,如果我发布任何太具体的东西,老板会杀了我的.我希望你能理解!

不过,我有一个完美的例子.没有任何不一致之处;) 好吧,好吧,确实有.然而,我相信,你们中的大多数人都足够聪明,能够理解这里的重要之处.

基本 struct :

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>>

对于ParkingSpot级的学生,我想到了这样的课程:

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
    }
}

从最后一点我得到了一堆

在作用域中找不到类型‘P’

这个也不起作用:

class ParkingSpot<V: Vehicle<P: Propulsion>>

应为"&gt;"以完成泛型参数列表

不过,此实现可以正常工作:

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示威性备忘录.

我使用了这个有点不寻常的名字来强调这一点.

(需要进行一些编辑,在我实际需要MotorP的地方错误地键入了Motor)

Update个个

我开着我喜欢的车在路上试了试:

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
        )
    )
)

Update个个

现在假设您正在使用第三方库,该库已经提供了一个很好的引擎实现.

您需要做的是为their个给定的类或 struct TheirMotor实现extension,它符合your协议MotorP:

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,并且需要使用适当的初始化器来创建它.

Ios相关问答推荐

设置堆栈视图的所有属性

从后台线程调用DispatchObject的方法安全吗?

将数据传回VC时委托为空

IOS-获取本地化系统映像

无法使用 NavigationView 和 NavigationLink 在 SwiftUI 中弹出当前屏幕

将 Riverpod 从 StateNotifier 修复为 NotifierProvider 以及应用程序生命周期监控

如果使用 .onAppear 设置,为什么 SwiftUI Picker 不显示正确的选定值

不可发送类型 '[String : Any]?'在调用非隔离实例方法 XXX 时退出主参与者隔离上下文不能跨越参与者边界

NSOperation 有延迟 - 它是异步的还是同步的?

SwiftUI - ScrollView 不显示底部文本

为什么我不能让 passthrough 科目为 combine 工作?

在 iPad 上删除列表的顶部和底部行

使用 @MainActor 更新 UI 的适当策略是什么?

通过MatchedGeometryEffect向上滑动视图

Xcode 缺少支持文件 iOS 12.2 (16E227)

无论我将构建版本或应用程序版本更改为什么,都会出现 ITEMS-4238冗余二进制上传错误

iOS Swift - 获取当前本地时间和日期时间戳

iOS在应用程序中下载并保存图像

在 Objective-C 中将所有文本转换为小写

Swift - 获取设备的 WIFI IP 地址