objective c:类和实例方法之间有什么区别?

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

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


正如大多数其他答案所说的那样,实例方法使用类的实例,而类方法只能与类名一起使用。Objective-C中定义如下:

1
2
3
4
5
6
@interface MyClass : NSObject

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

@end

它们可以这样使用:

1
2
3
4
[MyClass aClassMethod];

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

类方法的一些实际例子是许多基础类上的便利方法,比如NSString+stringWithFormat:NSArray+arrayWithArray:。实例方法将是NSArray-count方法。


所有的技术细节都在其他答案中得到了很好的描述。我只是想分享一个简单的类比,我认为它很好地说明了类和实例之间的区别:

enter image description here

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

enter image description here

实例(或对象)是您基于蓝图构建的实际房屋:您可以根据同一蓝图构建许多房屋。然后,您可以在每个房子中为墙壁涂上不同的颜色,就像您可以在不影响其他实例的情况下独立地更改类的每个实例的属性一样。


正如其他答案所说,实例方法操作对象并访问其实例变量,而类方法操作类作为一个整体,并且不能访问特定实例的变量(除非您将实例作为参数传递进来)。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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:

1
2
3
4
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的类,你可以这样做:

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

然后用户会调用:

1
[MathFunctions square:34];

而不必实例化类!

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

1
+ (NSArray *)arrayWithObject:(id)object

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

我希望您现在理解了什么时候和/或为什么应该使用类方法!!


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

在c#中,类方法被标记为静态的。没有标记为静态的方法和属性是实例方法。

1
2
3
4
class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}


我认为理解这一点的最好方法是看看allocinit。正是这种解释让我能够理解它们之间的差异。

类方法

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

实例方法

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

例子

1
NSString *myString = [NSString alloc];

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

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

通过在该实例上设置一些属性,可以修改名为myStringNSString的实例。注意消息的接收者是一个实例(类NSString的对象)。


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

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

类方法

操作类变量(它们不能访问实例变量)不需要实例化对象来应用吗有时可能是一种代码气味(一些刚接触OOP的人将其用作在OO环境中进行结构化编程的拐杖)

实例方法

操作实例变量和类变量必须有一个即时对象操作


如果我理解正确的话。

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

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

在大多数情况下(除非正在编写可重用库,否则不应该需要class变量)。


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

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


实例方法操作类的实例(即"对象")。类方法与类相关联(大多数语言对这些类使用关键字static)。


类方法

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

实例方法

另一方面,在调用类之前,需要该类的实例存在,因此需要使用new关键字创建类的实例。实例方法操作类的特定实例。实例方法不是作为静态声明的。


举个例子,有一款游戏中诞生了许多汽车。每一个都属于CCar类。实例化汽车时,它会调用

1
[CCar registerCar:self]

所以CCar类,可以列出每个实例化的CCar。假设用户完成了一个关卡,并想删除所有汽车……你可以:1-检查手动创建的每个CCar的列表,并执行whicheverCar.remove();或2-在CCar中添加一个removeAllCars方法,当您调用

1
时,该方法将为您完成该任务。例如<wyn>allCars[n].remove();</wyn></P><p>或者,您允许用户为整个应用程序指定默认字体大小,该字体大小在启动时加载并保存。如果没有类方法,您可能必须执行以下操作</P>[cc lang="c"]fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();

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

至于removeVowels函数,您将发现,像c#这样的语言实际上同时具有toLower或toUpper等特定方法。

例如myString.removeVowels()String.removeVowels(myString)(在ObjC中是[String removeVowels:myString])。

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

1
2
3
4
5
6
7
8
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]

虽然没有明确的答案,但是如果您觉得插入一个类方法可以改进您的代码,请尝试一下,并记住,一个类方法只允许您使用其他类方法/变量。


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

1
2
3
4
5
6
@interface MyClass : NSObject
// instance method
- (void) instanceMethod;

+ (void) classMethod;
@end

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

如果我们调用这些方法,区别就会很明显。这里的方法在MyClass中声明。

instance method需要一个类的实例:

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

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

1
2
3
4
-(void) someMethod
{
    [self instanceMethod];
}

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

1
[MyClass classMethod];

或者:

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

这不会工作:

1
2
3
4
// Error
[myClass classMethod];
// Error
[self classMethod];

类方法

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

的实例方法

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

调用

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

要调用类方法,可以直接将消息发送到类。

来源:IOS - Objective-C -类方法和实例方法


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


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

实例方法与方法之间不再有任何区别。在Objective-C语言中,自动引用计数后的类方法应运而生。

例如[NS StringWithformat:..] a类方法&[[NSString alloc] initwihtformat:..]一个实例方法,两者在ARC之后是相同的


注意:这只是伪代码格式

类方法

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

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

实例方法

相反,实例方法是在运行时发生的,因为只有在运行时,您才创建了某个对象的实例,该实例在每次实例化时都可能发生变化。

1
2
3
4
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,类型方法和类方法是一样的。


同样的思想也适用于变量。在讨论与方法/函数相同的变量时,您将遇到静态、成员、实例、类等术语。

在Obj-C社区中,常见的术语是ivar,例如变量,但是我还不是Obj-C的一员。


加上以上答案

类方法将在类上工作,我们将把它用于一般用途,如+stringWithFormat,类的大小,最重要的是用于init等

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

实例方法将在一个类的实例上工作而不是在一个类上,就像我们有两个人,我们想要知道每个人的平衡,我们需要使用实例方法。因为它不会返回一般响应。例如确定NSSArray的计数等。

1
2
[johnson getAccountBalance];
[ankit getAccountBalance];