【问题标题】:A method/property in a parent class returning an object from a child class父类中的方法/属性从子类返回对象
【发布时间】:2012-04-15 13:47:18
【问题描述】:

这很可能是一个愚蠢的问题,但无论如何。在目标 c 中,在子类的启动方法中,通常设置 self=[super init]。现在, self 属于子类,不需要转换,这意味着(或不......)父类的 init 方法以某种方式返回一个实际上属于子类的对象。

所以我的问题是:我可以在父类中定义其他方法或属性,当从子类调用时返回子类的对象?我认为Java中有类似的东西称为工厂方法,所以也许这个问题并不太离谱..

编辑 1. 让我更好地解释一下我的意思:我知道我可以在 ParentClass 方法中找到,我实际上是在对 ChildClass 类的对象进行操作。这是通过查看[self class]。但是,我想在 ParentClass 中声明一个方法,该方法返回子类中的一个对象,而无需事先知道子类将是哪个类。更好的是,我希望返回的对象甚至不需要正式的转换。

例如,我想要在父类中执行如下操作的方法:

-(ChildClass *) partialCopyOfSelf {
//returns an object which is a partial copy of self (only copying properties that also
// exist in parent class, but such that applying [result class] will yield the child class
// and will require no further conversion

(ChildClass *) copy=[[ChildClass alloc] init];
//now copy stuff
return copy;
} 

现在在子类中,我希望能够实现以下排序:

-(MyClass *) copyOfSelf {
MyClass *copy=[super partialCopyOfSelf];
// now copy properties that only exist in my child class
return copy;
}

编辑 2(来自我写给 @wbyoung 的评论)。 我想要这样做的原因是,在某些时候我可能想将父类的属性从 ivars 更改为可能只是计算一些例如,值,所以孩子不知道如何正确地复制它们。我写这篇文章是因为有人可能对如何完成同样的任务有更好的想法。

【问题讨论】:

    标签: objective-c oop


    【解决方案1】:

    init 方法实际上只是处理已经为子类创建的对象。这是对alloc 的调用。那是使用您向其发送消息的类来确定如何分配对象。

    话虽如此,您可以覆盖子类中的方法。消息总是发送到对象和方法查找从最顶层的类开始。

    您还可以执行[self class] 之类的操作来确定您在父类中的类型。不过,这只会让你走这么远。 [[self class] displayColor] 允许您在基类中实现方法和默认类方法实现,但根据需要在子类中覆盖类方法。

    【讨论】:

    • 回复:您的编辑。这似乎是个坏主意。您可以调用[[[self class] alloc] init] 来制作副本(甚至跳过init)然后根据需要分配值,但是使用部分副本似乎会遇到麻烦。
    • 是的,我想我能做到,谢谢!至于遇到麻烦——无论如何我都觉得有足够的冒险精神去尝试,但如果你能指定一个这种方法会很麻烦的场景,我会很高兴。我想要这样做的原因是,在某些时候我可能想将父类的属性从 ivars 更改为可能只是计算一些值,例如,这样孩子就不会知道如何正确复制它们。
    【解决方案2】:

    是的。 Obj-C 遵守大多数 OO 语言中的所有子类化规则。

    例如..

    @interface Foo : NSObject
    
    @property (readonly) BOOL thing1;
    @property (readonly) CGFloat width;
    
    @end
    
    @implementation Foo
    
    -(BOOL)thing1
    {
     return YES;
    }
    
    -(CGFloat)width
    {
     return 30.0f;
    }
    
    @end
    

    Bar 的接口不需要thing1width 的声明或实现。

    @interface Bar : Foo
    
    @end
    
    @implementation Bar
    
    -(BOOL)thing1
    {
    if(test) return YES; 
    else return NO;
    }
    
    -(CGFloat)width
    {
     return [super width] + 20.0f;
    }
    
    @end
    

    但是,您可以在子类中实现 thing1 和/或 width 以提供不同的值。

    父类的实例总是为属性thing1返回YES,而其子类Bar可以根据测试结果返回YES或NO(例如)。

    另一个属性width使用父类值并改变它。

    【讨论】:

      【解决方案3】:

      这很可能是一个愚蠢的问题,但无论如何。在 目标c,在一个子类的启动方法中,经常设置 自我=[超级初始化]。现在, self 属于子类,没有转换 是必需的,这意味着(或不是..)父级的 init 方法 类以某种方式返回一个实际上属于孩子的对象 类。

      嗯,不完全是。 -init 默认返回 id,它几乎是任何对象。它告诉编译器它是一个对象,并让它假设你知道你在做什么,所以你不需要强制转换它。


      所以我的问题是:我可以在一个 父类,当从子类调用时返回一个对象 从儿童班? Java中有类似的东西叫做 我认为工厂方法,所以也许这个问题不是太 太离谱了。。

      当您在超类的实现中返回self 时,您将返回与调用该方法的对象相同的对象。所以答案是肯定的。

      【讨论】:

      • 请查看我的新编辑,更好地解释我的意思。所以我从你的回答中猜想我可以在我的 partialCopy 方法中返回 id 类型并将其分配给子类中的 (MyClass *)?我想它应该可以工作,尽管它在捕获方面不如我想要的安全错误..
      猜你喜欢
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      • 2014-06-12
      • 1970-01-01
      相关资源
      最近更新 更多