ObjC中的自我是什么? 我应该什么时候使用它?
在Objective-C中, self
意味着什么? 何时何地应该使用它? this
在Java中是否类似?
self
指的是你正在工作的当前类的实例,是的, this
在Java中是非常类似的。
如果要对该类的当前实例执行操作,则使用它。 例如,如果您正在为某个类编写一个实例方法,并且您想调用同一个实例上的某个方法来执行某些操作或检索某些数据,则可以使用self
:
int value = [self returnSomeInteger];
如果它们实现了额外的function,而不是仅仅设置一个实例variables的值,那么这通常也用于实例上的访问方法(即setter和getter),特别是setter方法,这样就不必重复该代码,当你想要设置该variables的值时,例如:
[self setSomeVariable:newValue];
self
一个最常见的用途是在一个类的初始化过程中。 示例代码可能如下所示:
- (id)init { self = [super init]; if(self!=nil) { //Do stuff, such as initializing instance variables } return self; }
这将调用超类的(通过super
)初始化器,这就是如何在类层次结构上进行链式初始化。 然而,返回的值被设置为self
,因为超类的初始化器可能会返回与超类不同的对象。
self
是所有Obj-C方法的隐含参数,它们包含一个指向实例方法中当前对象的指针,以及一个指向当前类方法的指针。
另一个隐含的参数是_cmd
,它是发送给方法的select器。
请注意,您只能在Obj-C方法中使用self
和_cmd
。 如果你声明一个C(++)方法,例如作为一个C库的callback,你将不会得到self或者cmd。
有关更多信息,请参阅“Objective-C运行时编程指南”的“ 使用隐藏参数”部分。
是的,它与Java中的“this”完全相同 – 它指向“当前”对象。
两个重要的说明:
-
类本身,例如
UIView
(我不是在谈论一个UIView
对象)本身就是一个对象,并有一个self
关联。 所以举个例子,你可以像这样在类方法中引用self
:// This works +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Class method! +(void) makeTheMostOfYourself { }
-
请注意,编译器不会引发任何警告或错误,即使您要引用的
self
是对象而不是类。 这样很容易导致崩溃,例如:// This will crash! +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Object method! -(void) makeTheMostOfYourself { } // This will crash too! -(void) showYourself2 { [self performSelector: @selector(makeTheMostOfYourself2)]; } // Class method! +(void) makeTheMostOfYourself2 { }
不幸的是,这使得类方法有点难以使用,这是不幸的,因为它们是通过信息隐藏封装的有价值的工具。 小心一点
哇,那很多半正确的答案和误导性的提示。 这让我回答Q,即使有一个接受的答案多年:
首先:在早期绑定的情况下,将消息传递/调用的概念,作为Java的静态types化语言与后期绑定进行比较,dynamic地将语言作为Objective-C进行types化是非常困难的。 有一次,这将打破。 我会说:不,这是不相似的,因为两种语言的打字和发送的概念是根本不同的,所以没有什么可以相似的另一个。 但是,…
那么我们应该区分self
的“双方”。
A.使用自我
当你在一个消息中使用它时,它只是一个对象引用:
[self doSomething]; [anotherObject doSomething];
从技术上讲,两条线路的工作原理是相同的(当然,接受不同的接收机)。 这尤其意味着,第一行不会导致self
类中的方法的执行,因为self
并不一定是指“那个类”。 由于Objective-C中的每个消息(单个exception:消息到super
)都会导致在子类中执行一个方法:
@interface A : NSObject - (void)doSomething; - (void)doAnotherThing; @end @implementation - (void)doSomething { [self doAntoherThing]; } - (void)doAnotherThing { NSLog( @"A" ); } @interface B : A - (void)doSomething; // Not necessary, simply as a marker @end @implementation B - (void)doAnotherThing { NSLog( @"B" ); }
在这样的代码
B *b = [B new;] [b doSomething];
该线
[self doAnotherThing];
在A
类中将导致执行-doAnotherThing
( B
),因为到self
消息与其他消息一样迟到。 控制台上的结果是b“B”,而不是“A”。 使用 self
作为接收器,你不应该想到一个特殊的规则。 完全没有。
(上面的例子是在类方法中使用self
一个很好的例子,因为在类方法中可能会出现同样的情况,使用类本身打破了多态,在OOP中最糟糕的是什么。也是类方法。)
B. self
什么是self
指向? 它指向导致执行当前方法的消息发送到的对象。
有…
…[someObject doSomething]… // some object is a reference to an instance object
…作为一个消息,一个方法被称为,在最简单的情况下…
- (void)doSomething { … }
在这种情况下, self
可以指向该方法所属的类的一个实例 。 它可以指向一个子类的实例,该方法也属于。 你不知道。 (如上所述,这个信息被保存使用self
发送消息。)
如果消息被发送到一个类对象, self
指向类对象,那是消息的接收者。 这完全是类似的。 因此, self
指向一个子类对象是可能的:
@interface A : NSObject + (void)doSomething; + (void)doAnotherThing; @end @implementation + (void)doSomething { [self doAntoherThing]; } + (void)doAnotherThing { NSLog( @"A" ); } @interface B : A - (void)doSomething; // Not necessary, simply as a marker @end @implementation B + (void)doAnotherThing { NSLog( @"B" ); }
有这个类
…[A doSomething]…
self
-doSomething
( A
)中的self
指向B
的类对象。 因此B
(!)的[self doAnotherThing]
被执行。 这显然不同于
+ (void)doSomething { [A doAntoherThing]; }
后一种版本对OOP的原则造成了相关的伤害。
作为一个方面说明,根类的类方法中的self
可能指向根类或任何子类的实例对象。 在NSObject
上编写类别时,必须牢记这一点。
self是指向当前实例调度表的对象指针。 它是对象的每个成员函数的隐式第一个参数,并在调用该函数时被分配。
在像init这样的函数中,你需要小心的是当你调用超类init时,你可以重新指定self作为返回值,因为超类init可能会重新定义自己指向的内容。
super除了指向超类调度表之外,与自己类似。