将类扩展的继承子句迁移到协议扩展中

3
我将为您翻译以下内容:

我有一个VehicleModels框架,其中包括CarBikePlane等类。 在另一个名为VehicleInventory的框架中,我需要在表格中打印定制描述(特定于第二个框架)。因此,我添加了协议DescriptableVehicle,其中包含方法describe()。 然后,我为所有车辆添加了协议扩展,例如:

extension Car: DescriptableVehicle {
  func describe() -> String {
    return "Car: \(self.vin)" // returns formatted vehicle number
  }
}

然而,假设已经改变,现在我不再从我的车辆框架中公开具体类。相反,我公开了像CarProtocolBikeProtocol这样的协议,以便通常具有相同的信息。
问题是我不能再使用协议扩展(或者至少不是那种形式),因为与类的扩展相反,协议的扩展不能有继承子句。
有没有想法如何解决这个问题,以尽量不修改我的用法? 最初,我认为在协议上加上一些where子句再加上一些强制转换就可以了,但是由于无法访问类,这并没有帮助。 我也尝试过适配器和类型抹消,但要么我使用得不好,要么它的作用不同。
为了说明问题,我准备了一个存储库:https://github.com/wedkarz/SwiftProtocolExtensionsProblem 有两个游乐场。V1是我以前使用的,也是有效的。 V2包含我现在拥有的和我正在尝试使其工作的内容。
在现实生活中,类PrivateFramework是一个独立的框架和协议:VehicleProtocolCarProtocolBikeProtocolPlaneProtocol都是它的一部分,但DescriptableVehicle不是PrivateFramework的一部分,因此无法在其中使用。该示例说明了访问具体类型和其扩展的问题。您可以看到有一些扩展被注释掉,因为我不能再使用它们了。目标是使[VehicleProtocol]的集合以类似于先前工作的方式打印其内容。

你应该提供更多的代码,现在不太清楚你有什么问题。 - Alexander
好的,我会翻译。同时,您能指出哪里不清楚吗? - Fishman
我只是无法想象你目前拥有什么,你的目标是什么,以及什么正在困扰你。看到代码的最小可行性演示将有所帮助。 - Alexander
我已经准备好了一个存储库,以某种方式说明了我的问题。http://github.com/wedkarz/SwiftProtocolExtensionsProblem,请让我知道是否还有不清楚的地方。 - Fishman
1个回答

0

这个回答解决了你的问题吗?

class PrivateFramework {
    private class AbstractVehicle: VehicleProtocol {
        var name: String { return "Abstract vehicle name" }
    }

    private class Car: AbstractVehicle, CarProtocol {
        override var name: String { return "Car vehicle name" }
        let vin: String = "ABCDEFGH VIN"
    }

    private class Bike: AbstractVehicle, BikeProtocol {
        override var name: String { return "Bike vehicle name" }
        let saddle: String = "Comforable saddle name"
    }

    private class Plane: AbstractVehicle, PlaneProtocol {
        override var name: String { return "Plane vehicle name" }
        let numberOfEngines: Int = 4
    }

    func produceVehicles() -> [DescriptableVehicle] {
        let car = Car()
        let bike = Bike()
        let plane = Plane()
        return [car, bike, plane]
    }
}

protocol VehicleProtocol {
    var name: String { get }
}

protocol DescriptableVehicle: VehicleProtocol {
    func describe() -> String
}



protocol CarProtocol: DescriptableVehicle {
    var vin: String { get }
}

protocol BikeProtocol: DescriptableVehicle {
    var saddle: String { get }
}

protocol PlaneProtocol: DescriptableVehicle {
    var numberOfEngines: Int { get }
}




extension DescriptableVehicle where Self: CarProtocol {
    func describe() -> String { return "Car, \(self.name), \(self.vin)" }
}

extension DescriptableVehicle where Self: BikeProtocol {
    func describe() -> String { return "Bike, \(self.name), \(self.saddle)" }
}

extension DescriptableVehicle where Self: PlaneProtocol {
    func describe() -> String { return "Plane, \(self.name), \(self.numberOfEngines)" }
}

let vehicles: [DescriptableVehicle] = PrivateFramework().produceVehicles()

vehicles.forEach { print($0.describe()) }

不,DescriptableVehicle协议不是私有框架的一部分,因此您不能像func produceVehicles() -> [DescriptableVehicle]那样在内部使用它。这是另一个框架的功能。我的示例简化了一些,但我已经描述了规则。 - Fishman
因此问题出现了。原本我可以扩展具体类型,现在我有了接口。如何处理它(不更改私有框架)- 如何转换我的“曾经”的类扩展,以便我不必重写所有内容。 - Fishman
@Fishman,所以CarProtocol/BikeProtocol/PlaneProtocol不是PrivateFramework的一部分,但框架可以访问它们,但DescriptableVehicle不是框架的一部分,框架也无法访问它? - Alexander
这正如我在问题中描述的那样。'Car/Bike/Plane/VehicleProtocol'是私有框架的一部分,在外部公开可见。'DescriptableVehicle'不是框架的一部分。 - Fishman
让我们在聊天中继续这个讨论 - Alexander
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接