459

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

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

4

18 回答 18

681

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

@interface MyClass : NSObject

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

@end

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

[MyClass aClassMethod];

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

类方法的一些真实世界示例是许多 Foundation 类(如NSString's+stringWithFormat:NSArray's )上的便利方法+arrayWithArray:。实例方法将是NSArray's-count方法。

于 2009-06-27T21:19:09.380 回答
196

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

在此处输入图像描述

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

在此处输入图像描述

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

于 2013-05-08T08:01:31.150 回答
104

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

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

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

这需要一个对象,将其放入一个数组中,然后返回一个不需要内存管理的数组的自动释放版本,非常适合临时数组等等。

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

于 2009-06-27T21:57:06.010 回答
38

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

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

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}
于 2009-06-27T20:51:05.333 回答
16

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

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

类方法

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

实例方法

  • 对实例变量和类变量进行操作
  • 必须有一个实例化的对象才能操作
于 2009-06-27T20:57:19.720 回答
16

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

类方法

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

实例方法

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

例子

NSString *myString = [NSString alloc];

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

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

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

于 2012-11-07T09:50:41.110 回答
6

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

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

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

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

于 2013-05-24T01:35:59.563 回答
6

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

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

于 2010-11-09T06:16:55.203 回答
4

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

于 2009-06-27T20:51:52.727 回答
3

类方法

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

实例方法

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

于 2012-11-07T09:34:24.360 回答
3

In Objective-C all methods start with either a "-" or "+" character. Example:

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

+ (void) classMethod;
@end

The "+" and "-" characters specify whether a method is a class method or an instance method respectively.

The difference would be clear if we call these methods. Here the methods are declared in MyClass.

instance method require an instance of the class:

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

Inside MyClass other methods can call instance methods of MyClass using self:

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

But, class methods must be called on the class itself:

[MyClass classMethod];

Or:

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

This won't work:

// Error
[myClass classMethod];
// Error
[self classMethod];
于 2015-02-04T09:41:08.277 回答
3

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

[CCar registerCar:self]

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

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

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

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

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

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

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

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]

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

于 2011-11-16T10:17:35.940 回答
3

类方法


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


实例方法


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


调用


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

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


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

于 2016-01-23T18:10:29.653 回答
2

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

于 2011-03-17T15:55:10.837 回答
1

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

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

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

于 2013-02-25T07:02:11.717 回答
1

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

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

于 2012-01-18T14:12:38.430 回答
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,类型方法与类方法相同。

于 2016-06-12T19:18:40.650 回答
0

添加到上面的答案

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

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

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

[johnson getAccountBalance];
[ankit getAccountBalance];
于 2017-02-08T11:38:20.780 回答