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

类方法和实例方法的区别是什么?

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

338269 次浏览

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

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

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

Instances方法作用于类的实例(即“对象”)。类方法与类相关联(大多数语言使用关键字static来表示这些家伙)。

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

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

类方法

  • 操作Class变量(它们不能访问实例变量)
  • 不需要一个对象被实例化应用
  • 有时可能是一种代码气味(一些刚接触OOP的人把它作为在面向对象环境中进行结构化编程的拐杖)

实例方法

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

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

@interface MyClass : NSObject


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


@end

它们可以这样使用:

[MyClass aClassMethod];


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

类方法的一些真实例子是许多Foundation类中的方便方法,如NSString+stringWithFormat:NSArray+arrayWithArray:。实例方法是NSArray-count方法。

就像其他答案所说的,实例方法操作对象并可以访问它的实例变量,而类方法操作整个类,并且不能访问特定实例的变量(除非您将实例作为参数传入)。

类方法的一个很好的例子是counter类型方法,它返回类实例的总数。类方法以+开始,而实例方法以-开始。 例如:< / p >
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]);
< p >输出: 年龄:0 Number Of people: 2

.

另一个例子是,如果你有一个方法,你想让用户能够调用,有时把它变成一个类方法是很好的。例如,如果你有一个叫MathFunctions的类,你可以这样做:

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

然后用户会调用:

[MathFunctions square:34];

而不需要实例化类!

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

+ (NSArray *)arrayWithObject:(id)object

它接受一个对象,将其放入数组中,并返回数组的自动释放版本,不需要内存管理,这对于临时数组和类似的东西很好。

我希望你现在明白什么时候和/或为什么你应该使用类方法!!

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

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

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

以一款衍生出大量汽车的游戏为例。每个人都属于CCar班。 当一个car被实例化时,它调用

[CCar registerCar:self]
所以CCar类,可以列出每个实例化的CCar。 让我们假设用户完成了一个关卡,并想要移除所有汽车……你可以: 1-浏览你手动创建的每个CCar的列表,并执行whicheverCar.remove(); 或 2-添加一个removeAllCars方法到CCar,这将为你做,当你调用[CCar removeAllCars]。例如allCars[n].remove(); < / p > 或者,你允许用户为整个应用程序指定一个默认字体大小,在启动时加载和保存。 如果没有类方法,您可能必须执行类似

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

对于类方法,你可以使用[FontHandler getDefaultFontSize]

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

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

在这种情况下,实例可能调用类方法,因此两者都可用。 例如< / p >
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]

没有明确的答案,但是如果你觉得加入一个类方法可以改进你的代码,那就试试吧,记住类方法只能让你使用其他类方法/变量。

还要记住,同样的思想也适用于变量。在谈论变量时,你会遇到静态、成员、实例、类等术语,就像谈论方法/函数一样。

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

类方法

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

实例方法

另一方面,需要类的实例存在才能调用它们,因此需要使用new关键字创建类的实例。实例方法操作于类的特定实例。实例方法没有被声明为静态的。

我认为最好的理解方法是看allocinit。正是这个解释让我明白了其中的区别。

类方法

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

实例方法

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

例子

NSString *myString = [NSString alloc];

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

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

你正在修改名为NSString的实例myString,方法是在该实例上设置一些属性。注意消息的接收者是一个实例(NSString类的对象)。

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

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

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

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

enter image description here

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

enter image description here

实例(或对象)是你根据蓝图构建的实际房子:你可以用同一个蓝图建造很多房子。然后,您可以为每个房子的墙壁涂上不同的颜色,就像您可以独立地更改类的每个实例的属性而不影响其他实例一样。

如果我理解正确的话。

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

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

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

在Objective-C中,所有方法都以“-”或“+”字符开头。 例子:< / p >
@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内部,其他方法可以使用self调用MyClass的实例方法:

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

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

[MyClass classMethod];

或者:

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

这行不通:

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

类方法


类方法通常要么创建类的新实例,要么检索类的一些全局属性。类方法不能对实例进行操作,也不能访问实例变量。


实例方法


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


调用


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

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


来源:类方法和实例方法

注意:这只是伪代码格式

类方法

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

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,类型方法和类方法是一样的

补充上述答案

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

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

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

[johnson getAccountBalance];
[ankit getAccountBalance];