为什么NSMutableString继承自NSString而不是相反?

时间:2012-09-21 11:08:09

标签: objective-c ios cocoa-touch oop

NSMutableString继承自NSString,但

  1. 继承作为“是一种”关系。所以猫“是一个”动物。但NSMutableString“不是”NSString。 (因为NSString不能变异(不能改变))

  2. 通常,子类的作用是什么,然后基类应该能够做到。如鱼可以游泳,有些动物可以游泳。但NSMutableString可以更改,而NSString根本无法更改 - 任何NSString都无法更改。

  3. 那么为什么NSMutableString继承自NSString?此外,NSMutableArray继承自NSArrayNSString不应继承NSMutableArray instead,而是将“不更改标志”设置为YES吗?这背后的原理是什么?

    更新:一些答案​​会说:NSMutableString可以执行NSString可以执行的所有操作,因此NSMutableString会继承NSString。但是可以使用这个原则吗?石头可以保持不动。猫可以保持静止,可以移动。猫可以做石头所能做的所有事情,但我们不能让猫继承石头,对吗?

    如果我有两个游戏对象类:一个是弹性对象,一个是非弹性的,我认为将弹性对象作为基类实现是有意义的,而非弹性对象继承了它的标志外界无法改变。

5 个答案:

答案 0 :(得分:4)

  

继承作为“是一种”关系。所以猫“是一个”动物。但NSMutableString“不是”NSString

错误。 NSMutableString NSString,因为它可以执行 NSString所能做的任何事情。

  

通常,一个子类做什么,然后基类应该能够做

也错了。这是相反的方式。它更像是“基类可以做什么,它也必须由子类来完成”。

  

NSString不应该继承NSMutableArray吗?

我甚至没有看到两者之间的关系(只要wchar_t不是有效的Objective-C对象)。

All-in all:原因是NSMutableString能够做比NSString更多的事情,并且可以做NSString可以做的任何事情,因此是继承的方向。

答案 1 :(得分:1)

可变版本为不可变版本添加了额外的功能,这就是他们从另一个版本继承的原因。

但是你缺少的另一个原因是具有可变/不可变版本的类实际上是class cluster的成员,它隐藏了很多实现。所以你所想的是一个简单的类继承远不止于此。

继承还允许使用方便的方法来应用Liskov Substitution Principle

答案 2 :(得分:1)

子类< - >类关系通常被称为" is-a"关系。但实际上我认为Java的extends更好地描述了它:子类扩展了它的基类的功能。

NSString对象知道保存字符串和编码的所有内容 NSMutableString对象知道这一切,但另外知道如何更改存储的字符串,所以说" NSMutableString扩展NSString"

是完全合理的。

来自一条评论:

  

基类应该更广泛和一般。动物更广泛和一般,就像一个可变的弦更广泛和一般。一个不可变的字符串更多"特别"。这就是为什么以这种方式看待它,基本情况应该是可变的

是有意义的

NSString更通用,因为它为您创建了另一个子类,可以添加更改功能,而无需使用NSMutableString的实现,为什么您希望这样做。如果功能将放在NSString本身,你将只是第二次添加它,你的对象将携带代码,这是重复的,这将导致代码膨胀。还有很多情况,你的字符串不会改变,即按钮上的标签。如果将实体化为可变对象以及所有变异代码,那将是资源的浪费。

  

如果我有两个游戏对象类:一个是弹性对象,一个是非弹性的,我认为将弹性对象作为基类实现是有意义的,而非弹性对象继承了它的标志外界无法改变。

不,这将是一个弱设计,因为非弹性对象将携带所有代码,用于执行弹性行为。

答案 3 :(得分:0)

我认为继承意味着其原始类别,功能的扩大和多样性。哺乳动物通常是陆生动物,但海豚可能生活在海中。你可以说海豚继承了哺乳动物并扩大了它在海洋生活中的功能。

答案 4 :(得分:0)

说继承作为“是一种”关系起作用是真实的,但完全是误导性的。 “是一个”在英语中意味着“成为”的全部含义。在继承的情况下,“is a”仅表示子类型关系(并且编写类以便满足更强的Liskov替换原则要求是一种好的做法)。

一个更好的英语术语(仍然不完美,但更好)将是“X做Y所做的一切”。更好的是,在典型的OO术语中,它意味着“X拥有Y拥有的所有成员”。

NSMutable*确实是NS*的子类型而不是相反,因为任何(内在非变异)消息和NS*的属性也适用于NSMutable*而后者的任何变异消息或可变属性都不适用于前者。

通常,一个子类做什么,然后基类应该能够做到。是不正确的。事实上,反过来说。基类可以做什么,派生类也应该能够做到。

对于字符串和数组,在Objective-C数组中,字符串具有非常不同的方法集。只需检查课程文档。因此,它们在继承层次结构中完全分开(当然,除了常见的NSObject)。

关于你的石头和猫的例子,石头的唯一特征是它静止不动,猫的唯一特征是它静止不动或它可以移动,对于这些属性的合适定义,让猫从石头上继承是完全合理的。