[英]Swift Implicitly pass self as inout parameter for reference type
是否可以將self
作為inout
參數隱式傳遞,以在適當位置修改參考變量?
這是一種可以將抽象基類轉換為其具體子類之一的方法。 我的問題是,我必須始終擁有第一個參數obj: inout AbstractBaseClass
,還是可以隱式傳遞self。 我意識到這也可以表示為靜態方法。
func convertTo(_ obj: inout AbstractBaseClass, _ type: ConcreteClassTypes) {
switch type {
case .concreteClass1: obj = ConreteClass1()
case .concreteClass2: obj = ConcreteClass2()
}
}
這是完整的代碼:
class AbstractClass {
enum ConcreteType {
case concreteClass1
case concreteClass2
}
var id: Int = 0
fileprivate init() { }
func convert(_ obj: inout AbstractClass, to type: ConcreteType) {
let oldId = obj.id
switch type {
case .concreteClass1: obj = ConcreteClass1()
case .concreteClass2: obj = ConcreteClass2()
}
obj.id = oldId
}
class ConcreteClass1: AbstractClass {
override init() { super.init() }
}
class ConcreteClass2: AbstractClass {
override init() { super.init() }
}
}
var obj: AbstractClass = AbstractClass.ConcreteClass1()
obj.convert(&obj, to: .concreteClass2) //is there any way to eliminate this first argument?
像matt一樣,在這種情況下,我也不相信inout
是完成這項工作的正確工具。
話雖這么說,但如果您堅持這樣做,一種實現所需目標的方法是(濫用)協議擴展。 它們允許定義mutating
方法,該方法將隱式的self
參數傳遞為inout
(以允許采用值類型的變異)。
所以你可以說:
protocol AbstractClassProtocol {}
class AbstractClass : AbstractClassProtocol {
enum ConcreteType {
case concreteClass1
case concreteClass2
}
fileprivate init() {}
class ConcreteClass1: AbstractClass {
override init() { super.init() }
}
class ConcreteClass2: AbstractClass {
override init() { super.init() }
}
}
extension AbstractClassProtocol where Self == AbstractClass {
mutating func convert(to type: AbstractClass.ConcreteType) {
switch type {
case .concreteClass1:
self = AbstractClass.ConcreteClass1()
case .concreteClass2:
self = AbstractClass.ConcreteClass2()
}
}
}
var obj: AbstractClass = AbstractClass.ConcreteClass1()
obj.convert(to: .concreteClass2)
print(obj) // AbstractClass.ConcreteClass2
但這有點駭人聽聞,我會謹慎使用它。
...在適當位置修改參考變量? 這是一種可以將抽象基類轉換為其具體子類之一的方法。
您不是在“修改”或“轉換”任何東西。 您正在用一個對象替換另一個。 因此,這里沒有self
可以傳遞。 您正在做的事情的想法是摧毀一個self
並提供另一個self
。
也就是說,不清楚inout
變量是做什么用的。 您為什么不只分配新對象代替舊對象?
func giveMeA( _ type: AbstractClass.ConcreteType) -> AbstractClass {
switch type {
case .concreteClass1: return AbstractClass.ConcreteClass1()
case .concreteClass2: return AbstractClass.ConcreteClass2()
}
}
var obj: AbstractClass = AbstractClass.ConcreteClass1()
obj = giveMeA(.concreteClass2)
效果與您所做的相同 。 如果您認為不是,那只是在開玩笑inout
參數在做什么。
我將提出一種完全不同的方式來查看您要嘗試的操作。
沒有抽象超類。 沒有多個子類。 一類具有多種功能變體。 功能變體由類實例所擁有的幫助對象(結構)表示。
因此,要更改功能,只需將幫助程序設置為其他類型的幫助程序。 基本上,您可以給對象進行個性移植。
我有一個可以這樣工作的應用程序。 我有四個視圖控制器,它們以略微不同的方式呈現略微不同的信息。 但實際上,它們是一個視圖控制器和一個枚舉,其中有四種情況決定了這些差異。 因此,視圖控制器可以隨時將自己表現為四種類型中的任何一種。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.