簡體   English   中英

Swift隱式地將self作為引用類型的inout參數傳遞

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM