只是想知道:
在 NSString
中有一个名为 +stringWithString:
的静态方法。
这在 NSMutableString
中没有被重新声明/覆盖,所以我们不能假设这将返回一个 NSMutableString
。事实上,即使在 NSString 类中,返回类型也定义为 id 和 文档状态:
返回值
通过复制 aString
中的字符创建的字符串。
我在理解为什么它起作用并返回 NSMutableString 的知识中缺少目标 C 的哪一部分?特别是因为基类 NSString 不知道我们想要返回一个可变字符串。
有人可能会说,在内部调用了 [Class alloc]
,这将生成一个 NSMutableString
类型的对象,但即使这是纯粹的猜测,因为我们没有源代码,并且 < code>stringWithString: 可以在内部做任何它想做的事情。
所有这些类方法都在子类中重新实现吗?如果是的话,为什么没有记录下来?
Just wondering:
In NSString
there is a static method called +stringWithString:
.
This is not redeclared/overridden in NSMutableString
so we cannot assume that this will return an NSMutableString
. In fact even in the NSString class the return type is defined as id
and the doc states:
Return Value
A string created by copying the characters from aString
.
What part of objective C am I missing in my knowledge to understand why this works and returns an NSMutableString
? Especially because the base class NSString
is not aware that we want a mutable string in return.
One could say that internally [Class alloc]
is called which will generate an object of type NSMutableString
, but even this is pure guesswork as we do not have the source code and stringWithString:
could do whatever it wants internally.
Are all those class methods reimplemented in the subclass? And if yes why isn't this documented?
发布评论
评论(4)
更恰当地说,它是一个类方法。
在 cocoa 中,子类不需要重新声明该方法。事实上,它只会产生大量噪音(IMO)。它只需要重新定义方法来提供其自定义实现。
我们必须假设它将返回一个可变字符串。子类可以根据需要重新定义其初始值设定项和便利构造函数,以满足所需的约定,而无需公开重新声明该方法 - 仅当基类的实现不足时才需要定义该方法。
它“知道”是因为您编写了
[NSMutableString stringWithString:@"bah"]
而不是[NSString stringWithString:@"bah"]
。与实例方法一样,类方法有一个隐式的 self ,它允许它们通过类方法传递类型。因此,可以根据需要重新定义/覆盖类方法。类方法还可以使用 self 来确定或消息其类型(示例很快)。这不应该是猜测。在这种情况下,如果返回的是不可变字符串,您应该提交错误。否则,无论他们是否使用一个或多个定义,它都会像广告中所宣传的那样工作。
在便利构造函数的情况下,更常见的是通过指定的初始值设定项之一:
这样的实现可以采用以下形式:
尽管经常会出现异常,并且通常是优化的不可变/可变类型的情况:
当唯一的区别是您所请求的类类型时,不应重新声明或重新记录它们,除非它们与基类有一些偏差或有特殊说明 - 即使在这种情况下,最好使用另一个名称创建一个方法。
more approriately, it's a class method.
In cocoa, the subclass does not need to redeclare the method. In fact, it would just produce a lot of noise (IMO). It only needs to redefine the method to provide its custom implementation.
We must assume that it will return a mutable string. A subclass can redefine its initializers and convenience constructors as needed in order to meet the required contracts without publicly redeclaring the method -- it only needs to define the method when the base's implementation is insufficient.
It 'knows' because you have written
[NSMutableString stringWithString:@"bah"]
rather than[NSString stringWithString:@"bah"]
. Like instance methods, class methods have an implicitself
which allows them to pass the type through class methods. Therefore, class methods may be redefined/overridden as needed. The class methods may also useself
to determine or message their type (example shortly).It should not be guesswork. In this case, you should file a bug if you were returned an immutable string. Otherwise, it works as advertised, regardless of whether they used one or more definitions.
In the case of convenience constructors, it's more common to go through one of the designated initializers:
such an implementation could take the form:
although exceptions can often be made, and is often the case with optimized immutable/mutable types:
They should not be redeclared or redocumented when the only difference is the class type which you have requested, unless they have some deviation from the base class or special note -- even in that case, it would be better to create a method with another name.
NSMutableString
是NSString
的子类,因此任何调用NSMutableString
的方法都可以正常工作,并返回一个NSMutableString
> 当它有意义时。我想到的唯一不遵循这一点的方法是copy,按照惯例它返回一个不可变的实例。这就是为什么您的初始化方法返回
id
而不是具体实例,以及为什么所有类方法都应使用[self alloc]
而不是[MYActualClass alloc].
NSMutableString
is a subclass ofNSString
thus any method called onNSMutableString
can be expected to work appropriately, and return anNSMutableString
when it makes sense. The only method that comes to mind that doesn't follow that though iscopy
which by convention returns an immutable instance.This is why your initializer methods return
id
rather than a concrete instance, and why all class methods should use[self alloc]
instead of[MYActualClass alloc]
.(贾斯汀说的话,但需要澄清)
首先,Objective-C 没有静态方法。 Objective-C 有类方法。类方法的行为与实例方法完全相同(其中该类是元类的实例),并且可以继承、重写等...
因此,正如
NSMutableString
继承characterAtIndex:
并且可以重写它来执行一些特殊的操作,如果需要,NSMutableString
可以对类方法执行相同的操作。另请注意,类无需在标头中声明从其超类重写的方法。框架中的类通常不会显式声明重写方法,因为重写方法的行为应与父类完全相同,但会被重写以在子类要求的上下文中工作。
(What Justin said, but a clarification)
First and foremost, Objective-C does not have static methods. Objective-C has class methods. Class methods behave exactly like instance methods (where the class is an instance of a metaclass) and can be inherited, overridden, etc...
Thus, exactly as
NSMutableString
inheritscharacterAtIndex:
and can override it to do something special, if needed,NSMutableString
can do the same for class methods.Note also that there is no need for a class to declare a method in the header that it overrides from its superclass. The classes in the framework generally do not declare overridden methods explicitly because the overridden method should behave exactly as the parent, but is overridden to work within the context of the subclass's requirements.
您可以像这样编写初始化程序:
现在,当您在
NSString
上调用此初始化程序时,[self alloc]
返回NSString
并且您会得到一个NSString
返回的实例。但是当你调用[NSMutableString stringWithString:@"…"]
时,[self alloc]
消息的结果是NSMutableString
,因此初始化器返回一个可变字符串。You can write the initializer a bit like this:
Now when you call this initializer on
NSString
,[self alloc]
returnsNSString
and you get an instance ofNSString
back. But when you call[NSMutableString stringWithString:@"…"]
, the result of the[self alloc]
message isNSMutableString
, and therefore the initializer returns a mutable string.