类和实例方法有什么区别?

时间:2009-06-27 20:48:44

标签: objective-c oop methods class-method instance-methods

类方法和实例方法有什么区别?

实例方法是访问器(getter和setter),而类方法几乎是其他所有东西吗?

18 个答案:

答案 0 :(得分:661)

与大多数其他答案一样,实例方法使用类的实例,而类方法只能使用类名。在Objective-C中,它们被定义为:

@interface MyClass : NSObject

+ (void)aClassMethod;
- (void)anInstanceMethod;

@end

然后可以这样使用它们:

[MyClass aClassMethod];

MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];

类方法的一些真实世界示例是许多Foundation类的便捷方法,例如NSString的{​​{1}}或+stringWithFormat:的{​​{1}}。实例方法是NSArray的{​​{1}}方法。

答案 1 :(得分:191)

其他答案中已经很好地涵盖了所有技术细节。我只是想分享一个简单的类比,我认为很好地说明了类和实例之间的区别:

enter image description here

就像一个房子的蓝图:你只有一个蓝图,而且(通常)你不能仅仅用蓝图做那么多。

enter image description here

实例(或对象)是您根据蓝图构建的实际房屋:您可以从中构建大量房屋同样的蓝图。然后,您可以在每个房屋中为墙壁绘制不同的颜色,就像您可以独立更改类的每个实例的属性而不影响其他实例一样。

答案 2 :(得分:102)

与其他答案一样,实例方法对一个对象进行操作并可以访问其实例变量,而一个类方法作为一个整体对一个类进行操作,并且无法访问特定实例的变量(除非您传递实例作为参数)。

类方法的一个很好的例子是一个计数器类型方法,它返回一个类的实例总数。类方法以+开头,而实例方法以-开头。 例如:

static int numberOfPeople = 0;

@interface MNPerson : NSObject {
     int age;  //instance variable
}

+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
@end

@implementation MNPerson
- (id)init{
    if (self = [super init]){
          numberOfPeople++;
          age = 0;
    }    
    return self;
}

+ (int)population{ 
     return numberOfPeople;
}

- (int)age{
     return age;
}

@end

的main.m:

MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(@"Age: %d",[micmoo age]);
NSLog(@"%Number Of people: %d",[MNPerson population]);

输出: 年龄:0 人数:2

另一个例子是,如果你有一个你希望用户能够调用的方法,有时可以将它作为一个类方法。例如,如果您有一个名为MathFunctions的类,则可以执行以下操作:

+ (int)square:(int)num{ 
      return num * num;
}

然后用户会致电:

[MathFunctions square:34];

,无需实例化类!

您还可以使用类函数返回自动释放的对象,例如NSArray的

+ (NSArray *)arrayWithObject:(id)object

它接受一个对象,将它放在一个数组中,并返回一个不需要内存管理的数组的自动释放版本,非常适合temperorary数组,不适合。

我希望您现在明白何时和/或为什么要使用类方法!!

答案 3 :(得分:36)

实例方法适用于类的实例(即对象),而类方法适用于类本身。

在C#中,类方法标记为静态。未标记为static的方法和属性是实例方法。

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}

答案 4 :(得分:16)

我认为理解这一点的最佳方法是查看allocinit。正是这种解释让我理解了这些差异。

课程方法

类方法作为一个整体应用于类。如果检查alloc方法,那么这是方法声明之前由+表示的类方法。它是一个类方法,因为它应用于类来创建该类的特定实例。

实例方法

您使用实例方法来修改该实例唯一的特定类实例,而不是整个类。例如init(在方法声明之前用-表示)是一个实例方法,因为在使用alloc创建该类后,通常会修改该类的属性。

示例

NSString *myString = [NSString alloc];

您正在调用类方法alloc以生成该类的实例。注意消息的接收者是一个类。

[myString initWithFormat:@"Hope this answer helps someone"];

您正在通过在该实例上设置一些属性来修改名为NSString的{​​{1}}实例。注意消息的接收者是一个实例(类myString的对象)。

答案 5 :(得分:15)

您的问题的答案并非特定于objective-c,但是在不同的语言中,Class方法可能被称为静态方法。

类方法和实例方法之间的区别是

班级方法

  • 操作类变量(它们无法访问实例变量)
  • 不要求对象实例化以应用
  • 有时可能是代码气味(有些人不熟悉OOP用作在OO环境中进行结构化编程的拐杖)

实例方法

  • 操作实例变量和类变量
  • 必须有一个实例化对象才能进行操作

答案 6 :(得分:6)

类方法通常用于创建该类的实例

例如,[NSString stringWithFormat:@"SomeParameter"];返回一个NSString实例,其中包含发送给它的参数。因此,因为它是返回其类型对象的Class方法,所以它也称为便捷方法。

答案 7 :(得分:6)

所以,如果我理解正确的话。

class方法不需要您分配该对象的实例来使用/处理它。 class方法是自包含的,并且可以在不依赖于该类的任何对象的状态的情况下操作。期望class方法为其自己的所有工作分配内存并在完成时解除分配,因为该类的任何实例都不能释放先前调用类方法时分配的任何内存。

instance方法正好相反。除非您分配该类的实例,否则无法调用它。它就像一个普通的类,它有一个构造函数,可以有一个析构函数(清理所有已分配的内存)。

最有可能(除非您正在编写可重用的库,否则您不需要class变量。

答案 8 :(得分:4)

Instances方法对类的实例(即“对象”)进行操作。类方法与类相关联(大多数语言都为这些人使用关键字static。)

答案 9 :(得分:3)

课程方法

是声明为static的方法。可以在不创建类的实例的情况下调用该方法。类方法只能在类成员上操作,而不能在实例成员上操作,因为类方法不知道实例成员。除非在该类的实例上调用它们,否则也不能从类方法中调用类的实例方法。

实例方法

另一方面,

需要在调用类之前存在该类的实例,因此需要使用new关键字创建类的实例。实例方法对特定的类实例进行操作。实例方法未声明为静态。

答案 10 :(得分:3)

CLASS METHODS

类方法通常要么创建类的新实例,要么检索类的某些全局属性。类方法不对实例操作或对实例变量有任何访问权。

实例方法

实例方法对类的特定实例进行操作。例如,您实现的访问器方法都是实例方法。您可以使用它们来设置或获取特定对象的实例变量。

INVOKE

要调用实例方法,请将消息发送到类的实例。

要调用类方法,请直接将消息发送给类。

来源:IOS - Objective-C - Class Methods And Instance Methods

答案 11 :(得分:3)

在Objective-C中,所有方法都以“ - ”或“+”字符开头。 例如:

@interface MyClass : NSObject
// instance method
- (void) instanceMethod;

+ (void) classMethod;
@end

“+”和“ - ”字符分别指定方法是class method还是instance method

如果我们称这些方法,差异就会很明显。这里的方法在MyClass中声明。

instance method需要该类的实例:

MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];

MyClass内,其他方法可以使用MyClass调用self的实例方法:

-(void) someMethod
{
    [self instanceMethod];
}

但是,必须在类本身上调用class methods

[MyClass classMethod];

或者:

MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];

这不起作用:

// Error
[myClass classMethod];
// Error
[self classMethod];

答案 12 :(得分:3)

以一个产生大量汽车的游戏为例,每个都属于CCar类。 当汽车被实例化时,它会调用

[CCar registerCar:self]

所以CCar类可以列出每个实例化的CCar。 假设用户完成了一个级别,并希望删除所有车辆...您可以: 1-浏览您手动创建的每个CCar的列表,并执行whicheverCar.remove(); 要么 2-将一个removeAllCars方法添加到CCar,当您调用[CCar removeAllCars]时,它将为您执行此操作。即allCars[n].remove();

或者,例如,您允许用户为整个应用程序指定默认字体大小,该大小在启动时加载并保存。 如果没有类方法,您可能需要执行类似

的操作
fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();

使用类方法,您可以使用[FontHandler getDefaultFontSize]

至于你的removeVowels函数,你会发现像C#这样的语言实际上都有某些方法,比如toLower或toUpper。

e.g。 myString.removeVowels()String.removeVowels(myString)(在ObjC中为[String removeVowels:myString])。

在这种情况下,实例可能会调用类方法,因此两者都可用。 即。

public function toLower():String{
  return String.toLower();
}

public static function toLower( String inString):String{
 //do stuff to string..
 return newString;
}

基本上,myString.toLower()调用[String toLower:ownValue]

没有明确的答案,但是如果你觉得推动一个类方法会改进你的代码,试一试,并记住一个类方法只会让你使用其他类方法/变量。

答案 13 :(得分:1)

对上述答案的更新,我同意实例方法使用类的实例,而类方法只能与类名一起使用。

实例方法和实例之间没有任何区别。自动引用计数后的类方法在Objective-C中出现。

例如[NS StringWithformat:..]类方法& [[NSString alloc] initwihtformat:..]实例方法,在ARC

之后都相同

答案 14 :(得分:1)

还要记住,同样的想法适用于变量。在谈论与方法/函数相同的变量时,您会遇到静态,成员,实例,类等术语。

似乎Obj-C社区中的常用术语是ivar,例如变量,但我还不是Obj-C的人。

答案 15 :(得分:1)

类方法不能更改或知道任何实例变量的值。这应该是了解实例方法是否可以是类方法的标准。

答案 16 :(得分:1)

注意:这只是伪代码格式

班级方法

编译时期间,它所需做的几乎所有事情。它不需要任何用户输入,也不需要基于实例的计算。关于它的一切都基于类/蓝图 - 这是唯一的,即你没有一个类的多个蓝图。编译时可以有不同的变化吗?不,因此该类是唯一的,因此无论您调用类方法多少次,指向它的指针都是相同的。

PlanetOfLiving: return @"Earth" // No matter how many times you run this method...nothing changes.

实例方法

相反,实例方法在运行时发生,因为它只有你创建了一个可能在每个实例化时都有所不同的实例。

initWithName: @"John" lastName: @"Doe"Age:12 @"cool"
initWithName: @"Donald" lastName: @"Drumpf"Age:5 attitude:@"He started"
initWithName: @"President" lastName: @"Obama"Age:54 attitude: @"Awesome"
//As you can see the value can change for each instance.

如果您来自其他语言静态方法与类方法相同 如果您来自Swift,则类型方法与类方法相同。

答案 17 :(得分:0)

添加以上答案

类方法将在类上工作,我们将其用于通用目的,例如+ stringWithFormat,类的大小,最重要的是用于init等

NSString *str = [NSString stringWithFormat:@"%.02f%%",someFloat]; 

实例方法将对不在类上的类的实例起作用,就像我们有两个人一样,我们希望在这里分别知道每个的平衡,我们需要使用实例方法。因为它不会返回一般回复。例如比如确定NSSArray的数量等。

[johnson getAccountBalance];
[ankit getAccountBalance];