I'm trying to wrap my head around some of the differences in usage and syntax in C vs. Objective-C. In particular, I want to know how (and why) the usage differs for the dot operator and the arrow operator in C vs. Objective-C. Here is a simple example.
我试图把C和Objective-C在用法和语法上的差异总结出来。我特别想知道点运算符和箭头运算符在C和Objective-C中的用法是如何不同的。这里有一个简单的例子。
C Code:
C代码:
// declare a pointer to a Fraction
struct Fraction *frac;
...
// reference an 'instance' variable
int n = (*frac).numerator; // these two expressions
int n = frac->numerator; // are equivalent
Objective-C Code:
objective - c代码:
// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];
...
// reference an instance variable
int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator??
So, seeing how frac
is the same in both programs (i.e. it is a pointer to a Fraction object or struct), why are they using different syntax when accessing properties? In particular, in C, the numerator
property is accessed with frac->numerator
, but with Objective-C, it is accessed using the dot operator, with frac.numerator
. Since frac
is a pointer in both programs, why are these expressions different? Can anyone help clarify this for me?
那么,既然frac在两个程序中都是一样的(例如,它是一个指向一个分数对象或结构体的指针),为什么访问属性时使用不同的语法呢?特别是,在C中,frac->分子访问分子属性,而在Objective-C中,它使用点运算符,分形。分子访问。既然frac是两个程序中的指针,为什么这些表达式不同?谁能帮我澄清一下吗?
5 个解决方案
#1
72
frac
is actually not the same in both programs.
在两个程序中,frac都是不同的。
A C Fraction
is a struct
, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C
is with the dot (.
) operator. Objective-C maintains this operator when you use struct
s. For convenience, you can perform a dereference-and-dot operation using the arrow (->
) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing struct
s.
C部分是一个struct,它是没有重载操作符的基类型,并且只能在默认情况下构造和销毁。如果在结构体上定义函数或字段,那么访问C中这些属性的方法是使用dot(.)运算符。Objective-C在使用struct时维护这个操作符。为了方便起见,您可以使用箭头(->)操作符(您提到的两个等效表达式)执行一个derefer -and-dot操作。Objective-C在访问结构体时也保留了这一点。
An Objective-C Fraction
in your example, however, is probably (one would assume) a pointer of at least type id
, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject
or NSProxy
. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C
struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.
然而,在您的示例中,Objective-C分数可能(有人会认为)是一个至少具有类型id的指针,它只是一个类名和指向该类的实例的指针。它也很可能是NSObject或NSProxy的子类。这些Objective-C类的特殊之处在于,它们在一个C struct之上有一个完整的预定义操作层(如果您真的想深入研究它,那么您可以查看Objective-C Runtime引用)。同样需要注意的是,Objective-C类始终是指针。
One of the most basic operations is objc_msgSend
. When we operate on these types of objects, the Objective-C compiler interprets a dot (.
) operator or the square bracket syntax ([object method]
) as an objc_msgSend
method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.
最基本的操作之一是objc_msgSend。当我们操作这些类型的对象时,Objective-C编译器将点(.)运算符或方括号语法([object method])解释为objc_msgSend方法调用。有关这里实际发生的事情的更详细信息,请参阅比尔·本加纳(Bill Bumgarner)撰写的这一系列文章。本加纳是一名苹果工程师,负责监督object - c运行时的开发。
The arrow (->
) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]->
and then bring up the method completion list, you see this:
箭头(->)操作符并不真正应该用于Objective-C对象。如我所说,Objective-C类实例是一个C结构体,添加了一个额外的通信层,但是当使用箭头时,通信层基本上是被忽略的。例如,如果您打开Xcode并输入[UIApplication sharedApplication]->,然后打开方法完成列表,您会看到:
Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]
). These particular items, however, are the C
fields that store the values of their respective Objective-C properties.
在这里你可以看到一些我们通常使用方括号语法访问的普通字段(比如[UIApplication sharedApplication] delegate])。然而,这些特定的项是C字段,它们存储各自的Objective-C属性的值。
So, you can roughly think of it like this:
大致可以这样想:
Dot operator on a C object
C对象上的点操作符
- (at run time) Return value of the field
- (在运行时)字段的返回值
Arrow operator on a C object (pointer)
C对象上的箭头操作符(指针)
- Dereference pointer
- 废弃的指针
- Return value of the field
- 字段的返回值。
Dot operator/square brackets on an Objective-C object (pointer)
Objective-C对象(指针)上的点操作符/方括号
- (at compile time) Replace with call to
objc_msgSend
- (在编译时)替换为对objc_msgSend的调用
- (at run time) Look up Obj-C class definition, throw exception if something went wrong
- (在运行时)查找object - c类定义,如果发生错误就抛出异常
- Dereference pointer
- 废弃的指针
- Return value of the field
- 字段的返回值。
Arrow operator on an Objective-C object (pointer)
Objective-C对象(指针)上的箭头操作符
- (at run time) Dereference pointer
- (在运行时)撤销引用指针
- Return value of the field
- 字段的返回值。
Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.
这里我显然过于简化了,但是总结一下:箭头操作符在两种情况下基本上都是一样的,但是点操作符在Objective-C中有额外的/不同的含义。
#2
9
Dot-notation is a design choice. Since we always deal with pointers to objc instances, I'd guess the designers wanted something familiar, which also would not break existing programs. It was introduced in ObjC 2 - just a few years ago. Before that, you always had to use brackets for messaging.
点符号是一种设计选择。因为我们总是处理指向objc实例的指针,所以我猜设计者需要一些熟悉的东西,这也不会破坏现有的程序。就在几年前,ObjC 2引入了它。在此之前,您总是必须使用方括号来进行消息传递。
Dot notation makes a difference though - it is not direct access, but a message.
点表示法很重要——它不是直接访问,而是一条消息。
That is:
那就是:
obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;
val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;
You can still write obj->ivar
to access a pointer to object's members (if visible).
您仍然可以编写obj->ivar来访问对象成员的指针(如果可见的话)。
#3
6
In your first example, Fraction
is a struct. In your second example, Fraction
is an Objective-C class (and in iOS would likely be a subclass of NSObject
).
在第一个例子中,分数是一个结构体。在第二个示例中,Fraction是一个Objective-C类(在iOS中可能是NSObject的子类)。
C++ does not allow overloading of operator .
. Therefore without additional information you can deduce that the dot notation you're seeing is an additional language construct integrated into Objective-C, rather than a C/C++ defined or overloaded operator.
c++不允许重载操作符。因此,不需要额外的信息,您就可以推断出您所看到的点符号是一个集成到Objective-C中的附加语言结构,而不是一个C/ c++定义的或重载的操作符。
As it happens, the dot notation is simply a design feature the implementors chose as shorthand for property access, entirely equivalent to the square bracket getter:
碰巧,点表示法只是实现者选择作为属性访问简写的设计特性,完全等同于方括号getter:
myObjCVar.prop == [myObjCVar prop];
#4
2
The dot operator on objects is a special syntax for accessing objects' properties. It calls the property's getter or setter behind the scenes. So, for example, [@"hello" length]
and @"hello".length
are equivalent*. For all other types, the dot is the same as the C dot, and the arrow is always the same.
对象上的点运算符是访问对象属性的特殊语法。它在幕后调用属性的getter或setter。例如,[@"hello"长度和@"hello"长度。长度是相等的。对于所有其他类型,点与C点相同,而箭头总是相同的。
* Note: The accessor method won't always be named the same as the property. If it's a declared property and the declaration designates a special getter or setter method, that one will be used instead.
*注意:访问器方法的名称并不总是与属性相同。如果它是一个已声明的属性,并且声明指定了一个特殊的getter或setter方法,那么将使用这个方法。
#5
1
The dot and arrow notation are equally the same in C as it is in Objective-C (strict superset of ). I think the fundamental difference that needs to be distinguished is the difference between a struct and an Objective-C object.
点符号和箭头符号在C中与在Objective-C中一样(严格的超集)。我认为最基本的区别是结构体和Objective-C对象之间的区别。
The dot notation used for objects in Objective-C are used for properties that was introduced in Objective-C 2.0. However, with structs, the -> and dot notation between Objective-C and C are the same.
Objective-C中对象的点符号用于Objective-C 2.0中引入的属性。然而,对于结构体,Objective-C和C之间的->和点符号是相同的。
#1
72
frac
is actually not the same in both programs.
在两个程序中,frac都是不同的。
A C Fraction
is a struct
, which is a base type with no overloaded operators and is only really able to be constructed and destructed by default. If you define functions or fields on the struct, the way to access those properties in C
is with the dot (.
) operator. Objective-C maintains this operator when you use struct
s. For convenience, you can perform a dereference-and-dot operation using the arrow (->
) operator (the two equivalent expressions you mention). Objective-C also preserves this when accessing struct
s.
C部分是一个struct,它是没有重载操作符的基类型,并且只能在默认情况下构造和销毁。如果在结构体上定义函数或字段,那么访问C中这些属性的方法是使用dot(.)运算符。Objective-C在使用struct时维护这个操作符。为了方便起见,您可以使用箭头(->)操作符(您提到的两个等效表达式)执行一个derefer -and-dot操作。Objective-C在访问结构体时也保留了这一点。
An Objective-C Fraction
in your example, however, is probably (one would assume) a pointer of at least type id
, which is simply a classname and pointer to the instance of that class under the hood. It's also very likely to be a subclass of NSObject
or NSProxy
. These Objective-C classes are special in that they have a whole layer of predefined operations on top of just a C
struct (if you really want to dig into it then you can take a look at the Objective-C Runtime Reference). Also important to note, an Objective-C class is always a pointer.
然而,在您的示例中,Objective-C分数可能(有人会认为)是一个至少具有类型id的指针,它只是一个类名和指向该类的实例的指针。它也很可能是NSObject或NSProxy的子类。这些Objective-C类的特殊之处在于,它们在一个C struct之上有一个完整的预定义操作层(如果您真的想深入研究它,那么您可以查看Objective-C Runtime引用)。同样需要注意的是,Objective-C类始终是指针。
One of the most basic operations is objc_msgSend
. When we operate on these types of objects, the Objective-C compiler interprets a dot (.
) operator or the square bracket syntax ([object method]
) as an objc_msgSend
method call. For more detailed info about what actually happens here, see this series of posts by Bill Bumgarner, an Apple engineer who oversees the development of the Obj-C runtime.
最基本的操作之一是objc_msgSend。当我们操作这些类型的对象时,Objective-C编译器将点(.)运算符或方括号语法([object method])解释为objc_msgSend方法调用。有关这里实际发生的事情的更详细信息,请参阅比尔·本加纳(Bill Bumgarner)撰写的这一系列文章。本加纳是一名苹果工程师,负责监督object - c运行时的开发。
The arrow (->
) operator is not really supposed to be used on Objective-C objects. Like I said, Objective-C class instances are a C struct with an extra layer of communication added, but that layer of communication is essentially bypassed when you use the arrow. For example, if you open up Xcode and type in [UIApplication sharedApplication]->
and then bring up the method completion list, you see this:
箭头(->)操作符并不真正应该用于Objective-C对象。如我所说,Objective-C类实例是一个C结构体,添加了一个额外的通信层,但是当使用箭头时,通信层基本上是被忽略的。例如,如果您打开Xcode并输入[UIApplication sharedApplication]->,然后打开方法完成列表,您会看到:
Here you can see a bunch of normal fields which we generally access with square bracket syntax (like [[UIApplication sharedApplication] delegate]
). These particular items, however, are the C
fields that store the values of their respective Objective-C properties.
在这里你可以看到一些我们通常使用方括号语法访问的普通字段(比如[UIApplication sharedApplication] delegate])。然而,这些特定的项是C字段,它们存储各自的Objective-C属性的值。
So, you can roughly think of it like this:
大致可以这样想:
Dot operator on a C object
C对象上的点操作符
- (at run time) Return value of the field
- (在运行时)字段的返回值
Arrow operator on a C object (pointer)
C对象上的箭头操作符(指针)
- Dereference pointer
- 废弃的指针
- Return value of the field
- 字段的返回值。
Dot operator/square brackets on an Objective-C object (pointer)
Objective-C对象(指针)上的点操作符/方括号
- (at compile time) Replace with call to
objc_msgSend
- (在编译时)替换为对objc_msgSend的调用
- (at run time) Look up Obj-C class definition, throw exception if something went wrong
- (在运行时)查找object - c类定义,如果发生错误就抛出异常
- Dereference pointer
- 废弃的指针
- Return value of the field
- 字段的返回值。
Arrow operator on an Objective-C object (pointer)
Objective-C对象(指针)上的箭头操作符
- (at run time) Dereference pointer
- (在运行时)撤销引用指针
- Return value of the field
- 字段的返回值。
Now I'm definitely oversimplifying here, but to summarise: the arrow operators appear to do basically the same thing in both cases, but the dot operator has an extra/different meaning in Objective-C.
这里我显然过于简化了,但是总结一下:箭头操作符在两种情况下基本上都是一样的,但是点操作符在Objective-C中有额外的/不同的含义。
#2
9
Dot-notation is a design choice. Since we always deal with pointers to objc instances, I'd guess the designers wanted something familiar, which also would not break existing programs. It was introduced in ObjC 2 - just a few years ago. Before that, you always had to use brackets for messaging.
点符号是一种设计选择。因为我们总是处理指向objc实例的指针,所以我猜设计者需要一些熟悉的东西,这也不会破坏现有的程序。就在几年前,ObjC 2引入了它。在此之前,您总是必须使用方括号来进行消息传递。
Dot notation makes a difference though - it is not direct access, but a message.
点表示法很重要——它不是直接访问,而是一条消息。
That is:
那就是:
obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;
val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;
You can still write obj->ivar
to access a pointer to object's members (if visible).
您仍然可以编写obj->ivar来访问对象成员的指针(如果可见的话)。
#3
6
In your first example, Fraction
is a struct. In your second example, Fraction
is an Objective-C class (and in iOS would likely be a subclass of NSObject
).
在第一个例子中,分数是一个结构体。在第二个示例中,Fraction是一个Objective-C类(在iOS中可能是NSObject的子类)。
C++ does not allow overloading of operator .
. Therefore without additional information you can deduce that the dot notation you're seeing is an additional language construct integrated into Objective-C, rather than a C/C++ defined or overloaded operator.
c++不允许重载操作符。因此,不需要额外的信息,您就可以推断出您所看到的点符号是一个集成到Objective-C中的附加语言结构,而不是一个C/ c++定义的或重载的操作符。
As it happens, the dot notation is simply a design feature the implementors chose as shorthand for property access, entirely equivalent to the square bracket getter:
碰巧,点表示法只是实现者选择作为属性访问简写的设计特性,完全等同于方括号getter:
myObjCVar.prop == [myObjCVar prop];
#4
2
The dot operator on objects is a special syntax for accessing objects' properties. It calls the property's getter or setter behind the scenes. So, for example, [@"hello" length]
and @"hello".length
are equivalent*. For all other types, the dot is the same as the C dot, and the arrow is always the same.
对象上的点运算符是访问对象属性的特殊语法。它在幕后调用属性的getter或setter。例如,[@"hello"长度和@"hello"长度。长度是相等的。对于所有其他类型,点与C点相同,而箭头总是相同的。
* Note: The accessor method won't always be named the same as the property. If it's a declared property and the declaration designates a special getter or setter method, that one will be used instead.
*注意:访问器方法的名称并不总是与属性相同。如果它是一个已声明的属性,并且声明指定了一个特殊的getter或setter方法,那么将使用这个方法。
#5
1
The dot and arrow notation are equally the same in C as it is in Objective-C (strict superset of ). I think the fundamental difference that needs to be distinguished is the difference between a struct and an Objective-C object.
点符号和箭头符号在C中与在Objective-C中一样(严格的超集)。我认为最基本的区别是结构体和Objective-C对象之间的区别。
The dot notation used for objects in Objective-C are used for properties that was introduced in Objective-C 2.0. However, with structs, the -> and dot notation between Objective-C and C are the same.
Objective-C中对象的点符号用于Objective-C 2.0中引入的属性。然而,对于结构体,Objective-C和C之间的->和点符号是相同的。