魔术师和自定义类 - 理解标题和实现文件

时间:2012-10-02 07:09:47

标签: objective-c oop

我正在为Objective-C世界带来我的第一个绊脚石以及一本关于这个主题的书。我现在已经进入了内化创建和使用自定义类的概念的阶段。

而且我认为正确理解这些基本概念和原则是我未来学习Objective-C的关键,我只想跟你判断一下是否正确掌握了这些概念。

因此,在创建自定义类时,我已经明白这是在两个单独的文件中完成的 - 公共类头文件和类实现文件。为了将这个概念内化,我用一个“魔术师”在观众面前耍花招的方式将其理解为隐喻。

标题文件有点像魔术师表演的剧院外的海报。在进入之前,我们都可以看到魔术师的样子(属性)和他(它主要是“他”)可以执行的技巧(方法),以及他可以制作什么类型的东西他的魔术(类型声明) )。因此,从魔术师的这张“公共”海报(头文件)中,我可以理解他可以表演什么样的魔法以及他正在使用什么道具。也许有人提到这个特殊的魔术师已经从伟大的Houdini(阶级遗产和Houdini因此成为超类)中学到了一些技巧。

如果我被允许在后台,那么我就能真正看到他是如何做他的伎俩,也就是说,我可以查看魔术师的实施文件。

这个比喻是否与您如何理解自定义类的概念有关?

但是,我还没有弄清楚类方法和实例方法的概念是如何与这个比喻相关的?

你能否说实例方法属于魔术师这个特定“实例”在这个特定节目中表演的技巧类别,而类方法将是当代魔术师可以执行的技巧? 第三,方法使用“类型”的方式有点令人困惑。有些似乎是在接口文件中预先声明的,有些似乎只是在方法中被“声明”了吗?

举一个使用“魔术师”类的例子,我对头文件的理解可能如下所示:

@interface Magician : NSHoudini

// Instance method that given a variable of type rat it will turn this into something of type rabit 

-   (rabit) FromRatToRabit: (rat) aRat;

@end 

实现文件可能如下所示:

#import “Magician.h”

@implementation Magician

rabit aRabit 
// rabit being the type and aRabit the variable


-   (rabit) FromRatToRabit:(rat)aRat;
{

// some magic code goes here which will take what’s in the aRat variable, of type rat
// and turn it into a form of type rabit and return it in the aRabit variable 

aRabit
}
@end

如果上面的内容是正确的,我想知道为什么你没有声明你“提供”方法的aRat变量?或者在方法描述中使用它时是否认为已完成声明?

2 个答案:

答案 0 :(得分:2)

你的比喻是可以接受的。标题是其他文件的界面,用于告诉他们从该类/文件及其相应的实现文件(如果有的话)可以访问的文件

我在你的代码中注意到魔术师是Houdini的子类。我可能只是误解了你的例子,但就继承而言,这可能是不正确的。你说的是每个魔术师都是一种Houdini。如果说Houdini是一种魔术师,应该可以反过来。

类和实例已被多次解释,并不是特定于Objective C,因此我不会过多地介绍它。 Here is a post with some good answers。基本上,类函数/变量属于类本身,并不特定于该类的任何实例。类函数/变量的另一个词是static函数或变量。

不确定上一个问题是什么意思。目标c中的每个指针/变量都有一个类型。 你的语法搞砸了,这就是你发布的代码看起来应该是什么样的(是的,我纠正了兔子的拼写:-P)

@interface Houdini : Magician

// Instance method that given a variable of type rat it will turn this into something of type rabit 

- (Rabbit *) FromRatToRabit: (Rat *) aRat;

@end 

#import “Houdini.h”

@implementation Houdini

Rabbit *aRabbit; // this is an ivar, although you're not actually using it anywhere, I'm just correcting your syntax


- (Rabbit *) fromRatToRabit:(Rat *)aRat;
{

// some magic code goes here which will take what’s in the aRat variable, of type rat
// and turn it into a form of type rabit and return it in the aRabit variable 

  [aRat doSomethingToReturnRabbit]; // assuming rat has an instance function that returns a rabbit
}
@end

您可以通过执行类似

的操作来使用此功能
Houdini *myHoudini = [[Houdini alloc] init];
Rat *houdinisRat = [[Rat alloc] init];
Rabbit *houdinisRabbit = [myHoudini fromRatToRabbit:houdinisRat];

请注意,这取决于是否有鼠类和兔子类(您没有提供)。我也只是使用通常默认的初始化器。

希望这会有所帮助,您应该尝试单独搜索您有疑问的特定主题,因为有足够的阅读材料。

答案 1 :(得分:0)

这是理解公共接口和隐藏实现之间鸿沟的一个很好的比喻。但我认为你可能会有点卷入其中,我确实看到两个主要的误解 - “Houdini”是超类,而类方法是“所有技巧”。

评估继承层次结构敏感性的常用教科书方法是评估子类实例“是否是”超类实例。这可以在现实中变得非常抽象,但是,如果,例如,你正在设计魔术师公会医疗保险福利处理软件或其他东西,在这种情况下魔术师“是一个”绝对不是胡迪尼的东西!说他们都是自由职业者,所以每个魔术师“都是”1099承包商(美国自雇收入税表),或类似的东西。想到它的另一种方式是认为魔术师“是一个”舞台表演者,“是一个”艺人,等等。并不是说你总是想制作这样的软件,但它可以帮助我学习这个概念。

你说的第二件事就是如何思考课堂方法。考虑类方法行为和类型固有的信息,并且独立于任何实例。回到福利软件示例,让我们说所有魔术师公会会员获得401k(另一个美国税务代码,退休帐户),每个薪水支付$ X定义的贡献。现在假设这不是随着资历而变化的东西,这将是保持在班级水平的一个很好的信息。因此,魔术师可以执行的所有技巧都不是类方法 - 魔术师执行它们,因此它们将是实例方法。也许一系列被禁止的技巧(因为太危险)可能是一种阶级方法 - 这是一个魔术师固有的规则,但独立于任何一个魔术师。

最后,关于类型的第三个问题,我可以猜测你在问什么但不确定。假设你有一个方法

- (void)myMethod:(id)myArgument
{
    NSLog(@"myArgument = %@",myArgument);
}

那你在问myArgument在哪里宣布?它在方法签名中声明,它是方法的参数,您可以在方法体的范围内引用它(在花括号内)。不确定这是否是“即时”的意思。我担心你必须提供一些实际的源代码,而不是伪代码,并指出你想知道的具体地方。

还有一些关于术语的小问题,对不起,这已经过了很长时间 - 为一个方法“提供”一个值的术语通常是“通过”作为“参数”或“参数”。方法“描述”通常被称为方法签名或声明,有时候我会听到原型。是的,请澄清您所说的类型,类型声明等等,我不是100%明确你的问题。

希望这有帮助!