为什么NSWindow的contentView属性类型为id?

Bes*_*esi 5 cocoa objective-c nsview nswindow

为什么类的contentView属性而不是NSWindowidNSView

这对我来说没有意义,为什么contentView应该是除了NSView子类之外的任何东西.

所以在我的情况下,我必须这样输入它才能访问它的框架:

NSView *contentView = self.window.contentView; // returns an `id`
CGRect frame = contentView.frame
Run Code Online (Sandbox Code Playgroud)

而不是这,编译器不喜欢这样:

CGRect frame =  self.window.contentView.frame; // This does not compile
Run Code Online (Sandbox Code Playgroud)

小智 9

这可能是历史性的.Objective-C支持严格打字,但它也支持"鸭子打字",你不关心对象是什么,你关心它响应的消息(即它看起来像鸭子,它像鸭子一样嘎嘎叫,它可能是一只鸭子).您可以键入每个对象指针id并发送任何消息.实际上,接收者不需要为它接收的任何消息实现方法:它也可以将消息转发给另一个对象.

在Application Kit中 - OpenStep和Cocoa的前身GUI框架 - 几乎所有对象都是通过duck typing来使用的.这Window是Application Kit 3.2版的(部分)接口.

@interface Window : Responder
{
  NXRect frame;
  id contentView;
  id delegate;
  id firstResponder;
  id lastLeftHit;
  id lastRightHit;
  id counterpart;
  id fieldEditor;
  int winEventMask;
  int windowNum;
  float backgroundGray;
  //some bit masks indicating whether the window is visible, is key etc.
}
-contentView;
-setContentView:aView;
//more methods
@end
Run Code Online (Sandbox Code Playgroud)

请注意,contentViewivar被定义为a id,并且访问器方法中的所有类型也被隐式定义为id(因此-setContentView:返回一个对象:可能是Window实例self).这就是20世纪90年代早期大多数Objective-C代码的样子:应用工具包可能 20世纪90年代早期的大多数Objective-C代码.

NSWindow在AppKit的第一个版本中引入了 - 在1994年成为Cocoa的GUI框架.AppKit通常使用比Application Kit更严格的类型声明,但并没有严格遵守.实际上甚至可能是AppKit NSWindow包含来自Application Kit的代码Window,并且这个contentViewivar在更改中没有更新.

实际上,Objective-C变量中对类型一致性的严格要求是相对较新的.大多数严格性是通过属性声明(除了C存在并且支持强制类型之外的强类型)或通过更改允许可选方法的协议引入的,因此可以严格地键入委托对象.