0

我在 Objective-C 世界中迈出了我的第一个绊脚石,还有一本关于这个主题的书。我现在已经到了将创建和使用自定义类的概念内化的阶段。

我猜想正确理解这些基本概念和原则是我未来学习 Objective-C 的关键,我只是想和你核实一下是否正确掌握了这些概念。

因此,在创建自定义类时,我了解到这是在两个单独的文件中完成的——公共类头文件和类实现文件。为了将这个概念内化,我将其比喻为“魔术师”在观众面前表演魔术。

头文件有点像魔术师表演的剧场外的海报。在进入之前,我们都可以看到魔术师长什么样(属性),他(主要是“他”)可以执行哪些技巧(方法),以及他可以制作哪些类型的魔术(类型声明) )。因此从魔术师的这张“公开”海报(头文件)中,我可以了解到他可以施展什么样的魔术,使用什么道具。也许还提到了这位特殊的魔术师从伟大的胡迪尼(阶级遗产和胡迪尼因此成为超阶级)那里学到了一些技巧。

如果让我在后台,我就可以真正看到他是怎么弄的,也就是说,我可以查看魔术师的实现文件。

这个比喻会不会有点像您如何理解自定义类的概念?

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

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

以使用“Magician”类为例,我对头文件的理解可能是这样的:

@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 变量?或者当您在方法描述中使用它时是否认为声明已完成?

4

2 回答 2

2

你的比喻是可以接受的。标头是其他文件查看的接口,它告诉他们可以从该类/文件及其相应的实现文件(如果有的话)中访问什么

我在您的代码中注意到,尽管 Magician 是 Houdini 的子类。我可能只是误解了您的示例,但就继承而言,这可能是不正确的。你说的是每个魔术师都是胡迪尼的一种。应该说胡迪尼是魔术师的一种。

Class vs Instance 已经解释过很多次了,并不是针对 Objective C 的,所以我不会过多的涉及它。 这是一个有一些很好答案的帖子。基本上,类函数/变量属于类本身,并不特定于该类的任何实例。类函数/变量的另一个词是static函数或变量。

不知道你最后一个问题是什么意思。目标 c 中的每个指针/变量都有一个类型。不过,您的语法搞砸了,您发布的代码应该是这样的(是的,我更正了 rabbit 的拼写:-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];

请注意,这取决于有一个 rat 类和一个 rabbit 类(您没有提供)。我也只是使用通常的默认初始化程序。

希望这会有所帮助,您应该尝试更多地搜索您个人有疑问的特定主题,因为有大量可用的阅读材料。

于 2012-10-02T07:58:03.953 回答
0

这是理解公共接口和隐藏实现之间的鸿沟的一个很好的比喻。但是我认为您可能对此有点迷恋,并且我确实看到了两个主要的误解-“Houdini”是超类,而类方法是“所有技巧”。

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

您说的第二件事是如何思考类方​​法。考虑类型固有的类方法行为和信息,并且独立于任何实例。回到福利软件示例,假设所有魔术师公会成员都获得了 401k(另一个美国税法,退休账户),每张工资有 X 美元的固定缴款。现在假设这不是随资历而变化的东西,这将是一个很好的信息,可以保持在班级级别。因此,魔术师可以执行的所有技巧都不是类方法-魔术师执行它们,因此它们将是实例方法。也许禁用技巧列表(因为太危险)可能是一个类方法 - 这是作为魔术师固有的规则,但独立于任何单个魔术师。

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

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

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

还有一些关于术语的小问题,对不起,这太长了——将值“提供”给方法的术语通常是“传递”作为“参数”或“参数”。方法“描述”通常被称为方法签名或声明,有时我听到的原型。是的,请澄清你在谈论的类型、类型声明等等,我不是 100% 清楚你的问题。

希望这可以帮助!

于 2012-10-02T07:57:44.343 回答