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

What is the difference between class and instance methods?

提问人:Devoted 提问时间:6/28/2009 最后编辑:jscsDevoted 更新时间:11/8/2018 访问量:340954

问:

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

实例方法是访问器(getter 和 setter),而类方法几乎是其他一切吗?

objective-c oop 方法 class-method instance-methods

评论


答:

38赞 Robert Horvick 6/28/2009 #1

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

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

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

评论

1赞 Robert Horvick 6/28/2009
啊 - 对不起,我刚刚注意到这是一个 Obj-C 问题。希望我的答案仍然适用,但请投反对票或投票删除。
6赞 Quinn Taylor 6/28/2009
没有造成伤害。作为一般的 OOP 原则,您答案的第一部分是正确的,它绝对适用于 Objective-C。如果您不想看到此类问题,您可以将“objective-c”添加到标签列表中以忽略,尽管当然欢迎任何参与。:-)
4赞 eduffy 6/28/2009 #2

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

16赞 hhafez 6/28/2009 #3

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

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

类方法

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

实例方法

  • 对实例变量和类变量进行操作
  • 必须具有要操作的实例化对象

评论

0赞 蘇健豪 12/13/2016
实例方法可以对类变量进行操作吗?
683赞 Cory Kilger 6/28/2009 #4

就像大多数其他答案所说的那样,实例方法使用类的实例,而类方法可以只与类名一起使用。在 Objective-C 中,它们是这样定义的:

@interface MyClass : NSObject

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

@end

然后可以像这样使用它们:

[MyClass aClassMethod];

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

类方法的一些真实示例是许多基础类(如 's 或 's)上的便捷方法。一个实例方法将是 的方法。NSString+stringWithFormat:NSArray+arrayWithArray:NSArray-count

评论

7赞 Quinn Taylor 6/28/2009
好答案。还值得注意的是,您将看到用于描述方法的特定速记符号。例如,+[NSString stringWithFormat:] 是 NSString 上的类方法 +stringWithFormat:;-[NSArray objectAtIndex:] 是一个实例方法。具有多个选择器部分的方法编写为-[NSMutableDictionary,setObject:forKey:]等。您经常会在 Cocoa 响应、文档和 Xcode 中看到此表示法。
154赞 Brian Pan 1/14/2011
我想补充一点,类方法在许多其他语言中被称为“静态”方法。为了回答最初的问题,访问器是实例方法,因为它们正在设置和获取特定实例的状态。在上面的示例中,NSArray count 返回特定实例中的对象数。
2赞 user102008 7/23/2011
“而类方法只能与类名一起使用。” 或类对象
2赞 Pavan 7/4/2012
对不起,我的兴奋......但我刚刚了解了其中的区别,以及它的潜力。类方法摇滚,单例类也是如此!ufff 我坠入爱河了!<3
2赞 Sulthan 6/9/2013
@BrianPan静态方法和类方法并不相同。它们很相似,但它们命名不同的原因是它们的工作方式不同。例如,不能重写静态方法。
105赞 micmoo 6/28/2009 #5

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

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

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

主.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 数组等等。

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

评论

1赞 mobibob 2/19/2010
micmoo,我可以建议您将“static int numberOfPeople = 0;”放在代码格式的文本中吗?我很困惑,直到我在示例代码上方注意到它。除此之外,一个非常简洁的答案。
2赞 selytch 2/18/2013
请原谅我的新手困惑,但为什么您同时需要实例变量“age”和实例方法“age”?例如变量“age”的 getter 和 setter 不会用 @synthetize 创建吗?
0赞 micah94 6/28/2014
@selytch“年龄”必须定义为一个属性才能使用合成。
6赞 iosrookie 11/9/2010 #6

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

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

2赞 Deepee 3/17/2011 #7

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

评论

0赞 Elviss Strazdins 3/11/2015
-1,因为您可以将实例传递给类方法,它将能够更改并知道它的变量值。
3赞 sicklebrick 11/16/2011 #8

举个例子,一个游戏中会生成很多汽车。每个都属于 CCar 类。 当汽车被实例化时,它会调用

[CCar registerCar:self]

所以 CCar 类,可以对每个实例化的 CCar 做一个列表。 假设用户完成了一个关卡,并想移除所有汽车......您可以: 1- 浏览您手动创建的每个 CCar 的列表,然后执行或 2- 向 CCar 添加一个 removeAllCars 方法,当您调用 [CCar removeAllCars] 时,该方法将为您执行该操作。J.F.公司whicheverCar.remove();allCars[n].remove();

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

fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();

使用 class 方法,您可以摆脱 .[FontHandler getDefaultFontSize]

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

例如: 和(在 ObjC 中,这将是 )。myString.removeVowels()String.removeVowels(myString)[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]

没有明确的答案,但如果你觉得加入一个类方法会改进你的代码,那就试一试,并记住类方法只允许你使用其他类方法/变量。

1赞 Half_Duplex 1/18/2012 #9

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

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

3赞 iCrazyDev 11/7/2012 #10

Class 方法

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

实例方法

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

评论

0赞 Elviss Strazdins 3/11/2015
它也可以使用“alloc”关键字创建,而不仅仅是“new”。此外,Objective-C 不要求实例存在即可调用实例方法,您可以将消息发送到 null 指针。
16赞 Adam Waite 11/7/2012 #11

我认为理解这一点的最好方法是查看 和 .正是这种解释让我理解了其中的差异。allocinit

Class 方法

类方法将应用于整个类。如果检查该方法,则该类方法由 before 方法声明表示。它是一个类方法,因为它应用于类以创建该类的特定实例。alloc+

实例方法

使用实例方法修改类的特定实例,该实例对该实例是唯一的,而不是对整个类而言是唯一的。 例如(在方法声明之前用 a 表示)是一个实例方法,因为您通常在使用 .init-alloc

NSString *myString = [NSString alloc];

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

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

通过在 called 实例上设置某些属性来修改该实例。请注意消息的接收者如何是一个实例(类的对象)。NSStringmyStringNSString

评论

0赞 Ethan Parker 3/12/2014
检查“alloc”方法是什么意思?你能指出文档中的特定位置吗?(编辑) --> 啊,没关系,是的,在 NSObject 文档中,它说在“任务”下 - developer.apple.com/library/ios/documentation/cocoa/reference/......
0赞 Adam Waite 3/12/2014
你不需要真正了解它到底做了什么来掌握这一点,只需要把它应用到类中即可。简单地说:为对象分配足够的内存,将修改这些内存地址中的内容以定义对象的状态。除非有一个空间可以修改它,否则我们不能修改一个对象,所以我们使用类来决定给我们这个空间。allocinitalloc
1赞 user1292809 2/25/2013 #12

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

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

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

196赞 Johannes Fahrenkrug 5/8/2013 #13

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

enter image description here

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

enter image description here

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

评论

10赞 Shekhu 7/10/2015
@JohannesFahrenkrug 这里很好地解释了类和对象的概念。实际问题不是为了difference between class method and an instance method ;
0赞 Johannes Fahrenkrug 7/10/2015
@Aiden 谢谢。是的,你是对的,问题实际上是关于实例方法与类方法然而,OP的问题表明,类与实例的概念对他来说并不十分清楚。一旦这个概念明确了,其他部分就到位了。
1赞 Alex McPherson 1/13/2016
类与类实例的完美解释。对于新手来说,类是一个奇怪的概念,这以最基本的方式解释了它。
1赞 ChenSmile 2/16/2016
@JohannesFahrenkrug真的是一个很好的解释,这让我思考两者如何差异以及何时使用两者
6赞 Siddharth 5/24/2013 #14

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

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

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

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

评论

1赞 gnasher729 3/23/2014
需要类方法的一个明显情况是创建实例。您必须能够在没有任何实例的情况下创建实例,否则永远无法创建第一个实例。这就是为什么 +alloc 是并且必须是一个类方法。
3赞 Tulon 2/4/2015 #15

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

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

+ (void) classMethod;
@end

“+”和“-”字符分别指定方法是 a 还是 an。class methodinstance method

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

instance method需要类的实例:

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

里面其他方法可以调用实例方法:MyClassMyClassself

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

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

[MyClass classMethod];

艺术

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

这行不通:

// Error
[myClass classMethod];
// Error
[self classMethod];
3赞 Nam N. HUYNH 1/24/2016 #16

CLASS 方法


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


实例方法


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


调用


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

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


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

1赞 mfaani 6/13/2016 #17

注意:这只是伪代码格式

Class 方法

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

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,则类型方法与类方法相同。

0赞 garg 2/8/2017 #18

补充上述答案

Class 方法将适用于类,我们将将其用于通用用途,例如 +stringWithFormat、类的大小,最重要的是用于 init 等

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

实例方法将适用于类的实例,而不是像我们有两个人那样的类,我们想分别了解每个类的平衡,在这里我们需要使用实例方法。因为它不会返回一般响应。例如,确定 NSSArray 的计数等。

[johnson getAccountBalance];
[ankit getAccountBalance];