是否可以隐式传递self
作为inout
参数来修改参考变量?
这是一个可以将抽象基类转换为其具体子类之一的方法。我的问题是,我是否必须始终拥有第一个论点obj: inout AbstractBaseClass
,或者我可以隐含地传递自我。我意识到这也可以表示为静态方法。
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?
答案 0 :(得分:2)
像亚特一样,在这种情况下,我不相信inout
是适合这项工作的工具。
虽然如此,如果你坚持下去,实现你想要的一种方法是(ab)使用协议扩展。它们允许定义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
但这有点像黑客,我对使用它很谨慎。
答案 1 :(得分:1)
...修改参考变量到位?这是一个可以将抽象基类转换为其具体子类之一的方法......
您没有“修改”或“转换”任何内容。您将一个对象替换为另一个对象。因此,没有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
参数正在做什么。
答案 2 :(得分:0)
我将提出一种完全不同的方式来看待你正在尝试做的事情。
没有抽象的超类。没有多个子类。拥有一个具有多个功能变体的类。函数变体由辅助对象表示 - 一个由类实例拥有的结构。
因此,要更改功能,只需将帮助程序设置为其他类型的帮助程序即可。基本上,你给对象一个人格移植。
我有一个以这种方式运作的应用程序。我有四个视图控制器,以略微不同的方式呈现略有不同的信息。但实际上它们是一个视图控制器和一个枚举,其中有四个案例决定了这些差异。因此,在任何时候,视图控制器都可以将其自身表现为四种类型中的任何一种。