我試圖將物件型別轉換為使用泛型的類。這是一些代碼以更好地理解
我有一個名為 wheel
protocol Wheel
我有一個名為 Wings
class Wings {
var count = 2
}
現在,我有一個名為的泛型類 VehicleWrapper
class VehicleWrapper<T: Wings&Wheel> {
var vehicle: T
}
現在終于我有一個物件,我想對其進行型別轉換VehicleWrapper并使用類中的count屬性,Wings但我不知道型別T轉換時的型別。有沒有辦法對它進行型別轉換并使用count變數?
uj5u.com熱心網友回復:
您的問題的一個問題是您的代碼是非法的。你不能就這么說protocol Wheel;你需要花括號(它可能包含也可能不包含協議的要求)。而且您的 VehicleWrapper 沒有初始化程式,因此編譯器永遠不會允許它。
但是讓我們假設我們已經處理了所有這些。我的猜測是,您遇到的問題是不允許強制轉換為泛型。例如,您不能轉換為 VehicleWrapper。這是因為泛型不是型別。型別是決議的泛型。
為了顯示:
protocol Wheel {}
class Wings {
var count = 2
}
class VehicleWrapper<T: Wings & Wheel> {
var vehicle: T
init(vehicle: T) { self.vehicle = vehicle }
}
class Thing: Wings, Wheel {}
let thing = Thing()
class What<T: Wings & Wheel>: VehicleWrapper<T> {}
let what = What(vehicle: thing)
if let what = what as? VehicleWrapper { // compile error
print(what.vehicle.count)
}
如您所見,我們對 VehicleWrapper 的嘗試遭到了編譯器的蔑視。但是,我們可以合法地嘗試強制轉換為VehicleWrapper<Thing>.
你的問題的真正問題是,很難想象一個需要這樣做的用例,因為這個物件怎么會在你不知道它是什么的情況下首先出現?
uj5u.com熱心網友回復:
目前尚不清楚您想要實作的目標,但我認為泛型不是實作它的方法。
泛型本質上允許您定義型別的操作,而與這些型別無關。這與允許您定義可以對特定型別執行的操作的繼承或協議不同。
最重要的是,不同的通用物件型別不是協變的;之間不存在函式關系GenericClass<SuperClass>,并GenericClass<SubclassOfSuperClass>即使泛型型別確實有繼承關系。
以您為例,您可能最好使用某些協議。
考慮
protocol Wheeled {
var numberOfWheels: Int { get }
}
protocol Movable {
func moveForward()
func stop()
}
現在,我們可以Vehicle根據這些協議定義一個類和一些子類:
class Vehicle: Movable {
var name: String
var seatingCapacity: Int
init(name: String, seatingCapacity: Int) {
self.name = name
self.seatingCapacity = seatingCapacity
}
func moveForward() {}
func stop() {}
}
class Car: Vehicle, Wheeled {
var numberOfWheels: Int
init(name: String) {
self.numberOfWheels = 4
super.init(name: name, seatingCapacity: 5)
}
}
class Truck: Vehicle, Wheeled {
var numberOfWheels: Int
init(name: String) {
self.numberOfWheels = 18
super.init(name: name, seatingCapacity: 2)
}
}
現在,讓我們定義一架輕型飛機:
protocol Winged {
var numberOfWings: Int { get }
func takeOff()
func land()
}
class LightAirplane: Vehicle, Wheeled, Winged {
var numberOfWheels: Int
var numberOfWings: Int
init(name: String) {
self.numberOfWheels = 3
self.numberOfWings = 2
super.init(name: name, seatingCapacity: 4)
}
func takeOff() {}
func land() {}
}
使用這些定義,我們可以將一個Vehicle(無論是汽車、卡車還是飛機)問到moveForward()或stop()。
我們可以取一個符合 的物件Winged并將其請求為takeOff()和land()。
你可以在哪里使用泛型?讓我們看看我們的Truck- 我們可以把它變成一個泛型類:
class CargoTruck<Cargo>: Truck {
private (set) var cargo: Cargo?
init(name: String, cargo: Cargo? = nil) {
self.cargo = cargo
super.init(name: name)
}
func load(cargo: Cargo) {
self.cargo = cargo
}
func unload() {
self.cargo = nil
}
}
現在我們有一個Truck可以加載和卸載某種型別的子類,Cargo但我們的實作不需要關心它是什么:
struct Cattle {}
struct Appliance {}
var cattleTruck = CargoTruck(name:"Cattle Truck", cargo:[Cattle]())
var applianceTruck = CargoTruck(name:"Container Truck", cargo: Appliance()))
我們cattleTruck這是一個CargoTruck<[Cattle]?-也就是說它可以保持陣列Cattle和applianceTruck它是CargoTruck<Appliance>-它可以容納一個Appliance
如果我們想限制貨物的型別怎么辦 - 我們可以向泛型型別添加約束:
protocol ShippingContainer {
}
struct StandardContainer: ShippingContainer {
}
struct RefrigeratedContainer: ShippingContainer {
}
class ContainerTruck<Cargo: ShippingContainer>: CargoTruck<Cargo> {
}
let refer = ContainerTruck(name: "ReferTruck", cargo: RefrigeratedContainer())
refer.unload()
let bad = ContainerTruck(name:"Error", cargo: 12) // Error an Int is not a container
通用沒有定義卡車可以做什么(移動,裝卸等),而在于它做什么來-它可以load一ShippingContainer
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/368973.html
上一篇:為什么我不能在SwiftUI中符合Shape的內容上使用strokeBorder?
下一篇:計算屬性
