【问题标题】:How to instantiate a class in Objective-C that don't inherit from NSObject如何在 Objective-C 中实例化一个不继承自 NSObject 的类
【发布时间】:2012-01-21 15:17:15
【问题描述】:

鉴于此:

Person.h:

@interface Person 
{
}
- (void) sayHello;
@end

Person.m:

#import "Person.h"

@implementation Person 

- (void)sayHello 
{
    printf("%s", "Steve");
}

@end

如何实例化 Person?我试过这个:

Person *p = [Person new];

这样不行,这样也行:

Person *p = [Person alloc];

[更新]

我忘了说,我已经尝试过从 NSObject 继承,new 和 alloc 都可以。我只是好奇我们是否可以实例化一个不继承自 NSObject 的类?

【问题讨论】:

  • Person 继承自 NSObject 有什么问题?
  • +1 因为这是一个非常有趣的问题,虽然实用价值可能很少。
  • @Costique:没什么,只是我在网上找到的很多教程都没有提到这是一个要求(即从 NSObject 继承)。示例:en.wikibooks.org/wiki/Objective-C_Programming/syntax 尝试从 Object 继承,但 [Person new] 也不起作用
  • @Hao 大多数教程可能都没有提到它,因为它是一种从超类继承的面向对象编程中的给定,而根类通常称为 Object 或类似的东西。教程的作者往往会忘记,并不是每个人都知道这个事实,因为它是如此基本的东西。请阅读(并接受)乔希的回答,它应该彻底回答您的问题。如果您仍有任何问题,请随时发表评论。

标签: objective-c class instantiation


【解决方案1】:

你绝对可以这样做。你的类只需要实现+alloc 本身,就像NSObject 所做的那样。在基础上,这只是意味着使用malloc() 来获取足够大的内存块,以适应定义类实例的结构。

引用计数内存管理也不错(retain/release);这实际上是NSObject protocol 的一部分。您也可以采用协议并实现这些方法。

作为参考,您可以查看the Object class,它是类似于NSObject 的根ObjC 类,Apple 在其开源存储库中为Objective-C 运行时提供:

@implementation Object 

// Snip...

+ alloc
{
    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); 
}

// ...

- init
{
    return self;
}

// And so on...

话虽如此,您应该将NSObject 视为ObjC 运行时的一个组成部分。除了好奇、调查或实验之外,几乎没有任何理由实现您自己的根类(但是,根本不应该气馁)。

【讨论】:

  • +1 这绝对是正确的答案。确实,唯一您不想从 NSObject 继承的时候是您将在内存管理方面做一些根本不同的事情。
  • 一个关于objective-c的深刻答案超越了:“点击XCode中那个闪亮的按钮”......太棒了! +1
  • 这个答案是否也适用于swift?
  • 不,Swift 免费提供基本的类行为。
【解决方案2】:

你必须:

  1. 从 NSObject 继承,
  2. 使用您自己的 malloc 等进行“穷人”课程,或者
  3. 使用 Objective-C++ 并创建一个 C++ 类。

当然,其他两个都不适合Objective-C的存储管理,它们的调用协议等也不一样。

【讨论】:

  • 几乎!对于 2,您可以根据 malloc 和您自己的 refcount 简单地实现 +alloc、-retain、-release 等。通过实现 NSObject protocol,你可以透明地参与很多事情。
  • -1 你没有NSObject继承。有一堆类没有,比如NSProxy
  • @DaveDeLong 他的意思是你必须要么做 1. 2. 3.
【解决方案3】:

(很可能)没有充分的理由不想从 NSObject 继承,但这样做有很多充分的理由。

我很好奇你为什么不想从 NSObject 继承。我猜这源于缺乏知识而不是真正的需要。

但即使不知道原因:不要这样做。很难做到这一点,以至于它仍然可以与其他 Objective-C 类配合得很好,几乎是不可能的。

无论如何,您正在以一种隐藏实际完成的方式来实例化您的对象。在 Java 中,您通常通过默认构造方法 new 创建实例,而在 Objective-C 中,您通过在类上调用 alloc 然后在实例上调用 init 来实例化:

Person *aPerson = [[Person alloc] init];

可能只使用Person new,但我不会这样做,因为它隐藏了你真正所做的事情)

您实现您的类,以便从 NSObject 继承,然后,如有必要,编写您自己的 init 方法。

如果要登录控制台,请使用NSLog:

NSLog(@"Hello %@", @"Steven");

@"" 是 NSString 的特殊构造函数。Objective-C 中的字符串不是字节数组,而是对象。)

【讨论】:

  • 当然,在Objective-C中new只是原版alloc/init的简写。
【解决方案4】:

你不能……

Alloc 和 new ..copy init 所有这些方法都定义在 NSObject..

你也不能创建你自己的,因为苹果不提供 NSObject 实现类..所以你必须从 NSObject 或其子类继承,以便你可以初始化你的类

【讨论】:

  • 当然可以。苹果也做到了。你“只是”必须做你自己的 C 风格的内存管理。 NSObject 不是 Objective-C 语言的一部分,Foundation、UIKit、AppKit 也不是……
  • 我不明白为什么你没有删除这个答案,因为它显然是错误的。为自己赢得一个 Peer Pressure 徽章! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多