类方法和实例方法有什么区别?
实例方法是访问器(getter 和 setter),而类方法几乎是其他一切?
类方法和实例方法有什么区别?
实例方法是访问器(getter 和 setter),而类方法几乎是其他一切?
就像大多数其他答案所说的那样,实例方法使用类的实例,而类方法只能与类名一起使用。在 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
方法。
其他答案中很好地涵盖了所有技术细节。我只想分享一个简单的类比,我认为它很好地说明了类和实例之间的区别:
一个班级就像一栋房子的蓝图:你只有一个蓝图,而且(通常)你不能单独用蓝图做那么多。
一个实例(或一个对象)是您根据蓝图建造的实际房屋:您可以从同一个蓝图建造许多房屋。然后,您可以将每个房屋的墙壁涂成不同的颜色,就像您可以独立更改类的每个实例的属性而不影响其他实例一样。
就像其他答案所说的那样,实例方法对对象进行操作并可以访问其实例变量,而类方法对整个类进行操作并且无法访问特定实例的变量(除非您将实例作为范围)。
类方法的一个很好的例子是计数器类型方法,它返回类实例的总数。类方法以 开头+
,而实例方法以 开头-
。例如:
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
这需要一个对象,将其放入一个数组中,然后返回一个不需要内存管理的数组的自动释放版本,非常适合临时数组等等。
我希望您现在了解何时和/或为什么应该使用类方法!
实例方法适用于类的实例(即对象),而类方法适用于类本身。
在 C# 中,类方法被标记为静态。未标记为静态的方法和属性是实例方法。
class Foo {
public static void ClassMethod() { ... }
public void InstanceMethod() { ... }
}
您的问题的答案并不特定于objective-c,但是在不同的语言中,类方法可能被称为静态方法。
类方法和实例方法的区别是
类方法
实例方法
我认为理解这一点的最佳方法是查看alloc
and init
。正是这种解释让我理解了这些差异。
类方法
类方法作为一个整体应用于类。如果您检查方法,那是方法声明之前alloc
表示的类方法。+
这是一个类方法,因为它被应用于类以创建该类的特定实例。
实例方法
您使用实例方法来修改对该实例唯一的类的特定实例,而不是整个类。init
例如(-
在方法声明之前用 a 表示)是一个实例方法,因为您通常在使用 . 创建该类之后修改该类的属性alloc
。
例子
NSString *myString = [NSString alloc];
您正在调用类方法alloc
以生成该类的实例。注意消息的接收者是一个类。
[myString initWithFormat:@"Hope this answer helps someone"];
您正在通过在该实例上设置一些属性来修改被NSString
调用的实例。myString
注意消息的接收者是一个实例(类的对象NSString
)。
所以如果我理解正确的话。
方法class
不需要您分配该对象的实例来使用/处理它。方法class
是自包含的,并且可以在不依赖于该类的任何对象的状态的情况下运行。一个class
方法应该为它自己的所有工作分配内存并在完成时释放,因为该类的任何实例都不能释放在之前调用该类方法时分配的任何内存。
方法instance
正好相反。除非您分配该类的实例,否则您不能调用它。它就像一个普通的类,它有一个构造函数并且可以有一个析构函数(清理所有分配的内存)。
在大多数情况下(除非您正在编写可重用的库,否则您不需要class
变量。
类方法通常用于创建该类的实例
例如,[NSString stringWithFormat:@"SomeParameter"];
返回一个NSString
带有发送给它的参数的实例。因此,因为它是返回其类型对象的类方法,所以也称为便利方法。
实例方法对类的实例(即“对象”)进行操作。类方法与类相关联(大多数语言使用static
这些家伙的关键字)。
类方法
是声明为静态的方法。无需创建类的实例即可调用该方法。类方法只能对类成员进行操作,而不能对实例成员进行操作,因为类方法不知道实例成员。类的实例方法也不能从类方法中调用,除非它们是在该类的实例上调用的。
实例方法
另一方面,需要类的实例存在才能调用它们,因此需要使用 new 关键字创建类的实例。实例方法对类的特定实例进行操作。实例方法未声明为静态。
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];
以一个产生大量汽车的游戏为例。每辆汽车都属于 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]
没有明确的答案,但是如果您觉得将类方法推入会改进您的代码,请试一试,并记住类方法只会让您使用其他类方法/变量。
类方法通常要么创建类的新实例,要么检索类的一些全局属性。类方法不对实例进行操作,也不能访问实例变量。
实例方法对类的特定实例进行操作。例如,您实现的访问器方法都是实例方法。您可以使用它们来设置或获取特定对象的实例变量。
要调用实例方法,请将消息发送到类的实例。
要调用类方法,您可以直接将消息发送到类。
类方法不能改变或知道任何实例变量的值。这应该是知道实例方法是否可以是类方法的标准。
对上述答案的更新,我同意实例方法使用类的实例,而类方法可以仅与类名一起使用。
在Objective-C中出现自动引用计数后,实例方法和类方法之间没有任何区别。
例如[NS StringWithformat:..]
类方法和[[NSString alloc] initwihtformat:..]
实例方法,在 ARC 之后都相同
还要记住,同样的想法也适用于变量。在谈论变量时,您会遇到静态、成员、实例、类等术语,就像谈论方法/函数一样。
似乎 Obj-C 社区中的常用术语是 ivar 例如变量,但我还不是 Obj-C 人。
注意:这只是伪代码格式
类方法
几乎所有它需要做的就是在编译期间。它不需要任何用户输入,它的计算也不基于实例。关于它的一切都基于类/蓝图——这是独一无二的,即你没有一个类的多个蓝图。在编译期间你能有不同的变化吗?不,因此该类是唯一的,因此无论您调用类方法多少次,指向它的指针都是相同的。
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];
Instance Method将在一个类的实例上工作,而不是在一个类上工作,就像我们有两个人一样,我们想分别了解每个人的平衡,在这里我们需要使用实例方法。因为它不会返回一般响应。例如,确定 NSSArray 的计数等。
[johnson getAccountBalance];
[ankit getAccountBalance];