Objective C 和 C++ 中的可变性设计模式
-
26-09-2019 - |
题
最近对 iPhone 进行了一些开发,我注意到 iPhone SDK 中大量使用了一个有趣的设计模式,即对象可变性。
似乎典型的方法是定义一个不可变的类 NSFoo
, ,然后从中派生出一个可变的后代 NSMutableFoo
. 。一般来说, NSFoo
类定义数据成员、获取器和只读操作,以及派生的 NSMutableFoo
添加了 setter 和变异操作。
由于对 C++ 更加熟悉,我不禁注意到这似乎与我在 C++ 中编写相同代码时所做的完全相反。虽然你肯定 可以 采用这种方法,在我看来,更简洁的方法是创建一个单一的 Foo
类,将 getter 和只读操作标记为 const
函数,并在同一个类中实现可变操作和设置器。然后你会得到一个可变的类,但是类型 Foo const*
, Foo const&
等等,所有这些实际上都是不可变的等价物。
我想我的问题是,我对这种情况的看法有意义吗?我理解为什么 Objective-C 的做法有所不同,但是 C++ 中的二类方法有什么我错过的优点吗?或者我完全没有抓住要点?
这不是一个过于严肃的问题——更多的是出于我自己的好奇心。
解决方案
目标-C过动态。在C ++中常量资格在编译时被执行,并在运行时任何违反const的资格的(如修改通过非常量限定指针一个常量限定对象)是未定义的行为。
有部分相同,为什么有在Objective-C没有私有方法的原因。你是免费送你想要的任何消息,任何对象。运行时调度需要一个对象和一个消息,并且解决了一个方法实施来调用。
如果const
限定对象只能调用const
合格方法,这将完全破坏Objective-C和地基的动态特性,因为这样的检查需要在运行时进行(第一检查将确定是否正在发送的消息解析为一个常量限定实施的具体实例,另一个检查,以确定该实例本身是否是const限定)。考虑这个理论示例:
NSArray *mutableArray = [[NSArray alloc] init];
NSString *mutableString = @"I am a mutable string";
const NSString *immutableString = @"I am immutable because I am const-qual'd";
[mutableArray addObject:mutableString];
[mutableArray addObject:immutableString]; // what happens?!
// and what happens here (both immutable and mutable strings would respond
// to the same selectors because they are the same class):
[mutableArray makeObjectsPerformSelector:@selector(aMutableOperation)];
突然你失去动力。因为它是现在,可变的和不可改变的对象可以在一个不变的或可变集合在一起坐。
具有一个可变的子类保持目标C的动态性质,并保持运行时简单。有一个类似的话题在不久前关于私有方法。
其他提示
想法...
Mac,如您所知,在 C++ 中,您可以将“A”和“const A”视为两种不同的类型,它们唯一的关系是
- “A”和“A &”可以隐式转换为“const A”和“const A &”等......
- “const A &”可以 const_cast 为“A &”,等等...
编译器通过表达式等处理类型修饰符的继承和传播。
我猜 NS 的人会选择 ..Mutable..出于几个原因。我的第一个猜测是,我相信当 NextStep 最初被开创时,C 不支持“const”,而且它仍然没有面向对象。更重要的是,他们希望在可变与可变之间进行某些优化。不可变对象的实现。例如,在像 NSString 这样的不可变字符串类中,“池”字符串可能很有用。这允许重复的字符串被原子化,并且进程可能使用更少的内存。(它有一定的缺点,但总有权衡。)
在 C++ 中,你可以通过首先理解来朝着相同的方向前进 写时复制. 。std::string 据说可以做到这一点。
有趣的话题,
威尔·布拉德利