学习笔记之06-点语法

前言

在Java中,我们可以通过"对象名.成员变量名"来访问对象的公共成员变量,这个就称为"点语法"。比如:

1.在Student类的第2行定义了一个公共的成员变量age

1 public class Student {
2     public int age;
3 }

2.然后在第5行通过点语法直接给stu的成员变量age赋值

1 public class Test {
2
3     public static void main(String[] args) {
4         Student stu = new Student();
5         stu.age = 10;
6     }
7
8 }

当然,正规的做法是让成员变量私有化,让外界使用公共的get方法和set方法访问成员变量。

3.很多高级语言中都有这种点语法,为了让其他行业的程序员快速上手OC,OC中也引入了点语法,只不过它的含义跟Java不太一样

一、传统的get方法和set方法

在正式学习OC的点语法之前,先来看一下传统的get方法和set方法。定义一个Student类,拥有一个成员变量age和对应的get\set方法。

1.Student.h

 1 #import <Foundation/Foundation.h>
 2
 3 @interface Student : NSObject {
 4     int age;
 5 }
 6
 7 - (void)setAge:(int)newAge;
 8 - (int)age;
 9
10 @end

1> 在第4行定义了一个成员变量age,是@protected权限的,所以外界不能直接访问它

2> 在第7、8行分别声明了age变量的set方法和get方法

2.Student.m

 1 #import "Student.h"
 2
 3 @implementation Student
 4
 5 - (void)setAge:(int)newAge {
 6     age = newAge;
 7 }
 8
 9 - (int)age {
10     return age;
11 }
12
13 @end

1> 在第5行实现了set方法

2> 在第9行实现了get方法

3.main.m

把定义好的Student类放到main函数中使用

 1 #import <Foundation/Foundation.h>
 2 #import "Student.h"
 3
 4 int main(int argc, const char * argv[])
 5 {
 6     @autoreleasepool {
 7         Student *stu = [[Student alloc] init];
 8
 9         // 设置age的值
10         [stu setAge:10];
11
12         // 取出age的值
13         int age = [stu age];
14
15         NSLog(@"age is %i", age);
16
17         [stu release];
18     }
19     return 0;
20 }

1> 在2行包含Student的头文件

2> 在第7行创建Student对象,在第17行释放Student对象

3> 在第10行调用set方法设置age的值

4> 在第13行调用get方法获取age的值

5> 在第15行输出age的值,输出结果如下:

2013-04-08 00:26:19.002 点语法[6164:303] age is 10

这就是OC传统的get方法和set方法的简单使用,对初学者来说,这个语法比较奇怪,因为它的方法调用是用方括号[ ]完成的。因此,OC最终引入了点语法。

二、使用点语法代替传统的get方法和set方法

上面演示了OC传统get\set方法的简单用法,接下来使用点语法来代替。

前面main.m中main函数的代码可以改为:

 1 int main(int argc, const char * argv[])
 2 {
 3     @autoreleasepool {
 4         Student *stu = [[Student alloc] init];
 5
 6         // 设置age的值
 7         stu.age = 10; // 等价于[stu setAge:10];
 8
 9         // 取出age的值
10         int age = stu.age; // 等价于int age = [stu age];
11
12         NSLog(@"age is %i", age);
13
14         [stu release];
15     }
16     return 0;
17 }

1.注意第7行代码,把原来的[stu setAge:10]替换成了stu.age = 10。听清楚了,这两种写法是完全等价的。即这里的stu.age并不是代表直接访问stu对象的成员变量age,而是编译器遇到stu.age = 10的时候会自动将代码展开成[stu setAge:10]

再说,如果是直接访问成员变量的话,OC中应该是这样的语法:stu->age,而不是stu.age。

2.注意第10行代码,把原来的int age = [stu age]替换成了int age = stu.age。这两种写法又是完全等价的,stu.age并不是直接访问stu对象的成员变量age,而是编译器遇到int age = stu.age的时候会自动将代码展开成int age = [stu age]

3.因此,OC中点语法的含义跟Java是完全不一样的,OC点语法的本质是方法调用,不是直接访问成员变量。至于这个点语法代表的是get方法还是set方法,那就取决于你是取值还是设值,取值就是get方法(如第10行代码),设值就是set方法(如第7行代码)。

4.如果你想验证点语法是不是方法调用的话,有很多方法。

比如你可以在Student.m的set方法和get方法内部用NSLog加一些打印信息,如果程序运行后有输出打印信息,说明的确是调用了get方法或者set方法

 1 #import "Student.h"
 2
 3 @implementation Student
 4
 5 - (void)setAge:(int)newAge {
 6     NSLog(@"调用了setAge方法");
 7     age = newAge;
 8 }
 9
10 - (int)age {
11     NSLog(@"调用了age方法");
12     return age;
13 }
14
15 @end

三、点语法和self的陷阱

1.在Java中,this关键字代表着方法调用者,也就是说,谁调用了这个方法,this就代表谁。所以一般会这样写set方法:

1 public void setAge(int newAge) {
2     this.age = newAge;
3 }

第2行表示将newAge参数的值,赋值给方法调用者的成员变量age

2.OC中有个self关键字,作用跟this关键字类似。我这么说完,可能有人就会想这样写OC的set方法了:

1 - (void)setAge:(int)newAge {
2     self.age = newAge;
3 }

第2行中的self代表着当前调用setAge:方法的对象。但是第2行代码是绝对错误的,会造成死循环。因为我在前面已经说过了,OC点语法的本质是方法调用,所以上面的代码相当于:

1 - (void)setAge:(int)newAge {
2     [self setAge:newAge];
3 }

很明显,会造成循环调用setAge:方法,程序就这样崩溃了

四、一点小建议

如果是第一次接触OC的点语法,你可能会真的 以为stu.age的意思是直接访问stu对象的成员变量age。其实,有一部分原因是因为我这里定义的Student类的成员变量名就叫做age。为了 更好地区分点语法和成员变量访问,一般我们定义的成员变量会以下划线 _ 开头。比如叫做 _age 。

1.Student.h,注意第4行

 1 #import <Foundation/Foundation.h>
 2
 3 @interface Student : NSObject {
 4     int _age;
 5 }
 6
 7 - (void)setAge:(int)newAge;
 8 - (int)age;
 9
10 @end

2.Student.m,注意第6行和第10行

 1 #import "Student.h"
 2
 3 @implementation Student
 4
 5 - (void)setAge:(int)newAge {
 6     _age = newAge;
 7 }
 8
 9 - (int)age {
10     return _age;
11 }
12
13 @end

时间: 2024-12-25 16:15:53

学习笔记之06-点语法的相关文章

【Ext.Net学习笔记】06:Ext.Net GridPanel的用法(GridPanel 折叠/展开行、GridPanel Selection、 可编辑的GridPanel)

GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候. 下面来看看效果: 使用行折叠/展开功能之后,在Ext.Net GridPanel的行头会出现一个展开图标,点击图标以后能够将这一行展开: 使用XTemplate实现行折叠/展开 这是最简单的一种实现,在上一篇文章:[Ext.Net学习笔记]05:Ext.Net GridPanel的用法(包含Filter.Sorter.Grouping.汇

HTML&CSS基础学习笔记3-HTML的标签语法

HTML标签语法 1. 标签由英文尖括号<和>括起来,如<html>就是一个标签. 2. HTML中的标签一般都是成对出现的,分开始标签和结束标签.结束标签比开始标签多了一个/.如: <p></p> 3.标签的内容是开始标签与结束标签之间的内容,如:<h1>这是标题</h1>. 4. 标签与标签之间是可以嵌套的,但先后顺序必须保持一致,如:<div>里嵌套<p>,那么</p>必须放在</div

Scala学习笔记一之基础语法,条件控制,循环控制,函数,数组,集合

前言:Scala的安装教程:http://www.cnblogs.com/biehongli/p/8065679.html 1:Scala之基础语法学习笔记: 1:声明val变量:可以使用val来声明变量,用来存放表达式的计算结果,但是常量声明后是无法改变它的值的,建议使用val来声明常量: 声明var变量:如果要声明可以改变的引用,可以使用var变量,声明的常量的值可以改变. 3:指定类型:无论声明val变量还是声明var变量.都可以手动指定其类型,如果不指定,scala会自动根据值,进行类型

Duilib学习笔记《06》— 窗体基类WindowImpBase

在前面的例子中我们发现,窗口都是继承CWindowWnd.INotifyUI,然后重载相关函数去实现.显然,我们发现窗口的创建流程实际上都是差不多的,主要只是在OnCreate加载的配置文件不同等等…所以,能不能创建一个公有的窗体基类呢?其实,在duilib中已经提供了一个窗体基类 WindowImplBase:在基类内搭建窗口的消息框架,各处理函数为虚函数,子类可以重载处理函数,实现其处理. 此处我们以修改之前的代码为例来进行说明. 1. 窗体显示 CMainWndDlg类修改为继承Windo

【C#学习笔记】1.基本语法结构

关键字:C#的关键字全部大写 注释:跟C++ / Java 风格一致,///是文档注释,只能写在类.方法.属性的前面.不能用来注释单个变量. C#语言也是严格区分大小写的 C#中的常量: 常量,顾名思义,就是"不会改变的量". 我们平时书写的数字(比如12.85).字符(比如'F').字符串(比如"谢谢"),它们都属于"字面常量". 有一些常量既重要又容易出错,比如圆周率π的值为3.1415926......,所以,我们常常会使用自定义常量.请看

Java基础学习笔记四 Java基础语法

数组 数组的需求 现在需要统计某公司员工的工资情况,例如计算平均工资.最高工资等.假设该公司有50名员工,用前面所学的知识完成,那么程序首先需要声明50个变量来分别记住每位员工的工资,这样做会显得很麻烦. 数组的概述 数组是指一组数据的集合,数组中的每个数据被称作元素.在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致. 数组的定义 格式: 数据类型[] 数组名 = new 数据类型[元素个数或数组长度]; 举例:int[] x = new int[100]; 要点说明 数据类

Java基础学习笔记三 Java基础语法

Scanner类 Scanner类属于引用数据类型,先了解下引用数据类型. 引用数据类型的使用 与定义基本数据类型变量不同,引用数据类型的变量定义及赋值有一个相对固定的步骤或格式. 数据类型 变量名 = new 数据类型(); 每种引用数据类型都有其功能,我们可以调用该类型实例使用其功能. 变量名.方法名(); Scanner类 Scanner类可以完成用户键盘录入,获取到录入的数据. Scanner使用步骤: 导包: import java.util.Scanner; 创建对象实例:Scann

【Smallfan的ios学习笔记 02】基础语法

本文来自:博客园CoderSmallfan.转载请注明出处:http://www.cnblogs.com/codersmallfan/p/3746837.html 学习ios的同学一般都是具备一定的编程语言基础,所以基础语法这块的东西并不需要像"谭xx 叫兽"那种一步一个脚印儿地学,一般也就看看异同点.objective-c这门语言是由c派生出来的,所以面向过程方面的东西是完全和c相同的,而新增的面向对象方面的知识点,多应与c++进行比较,这也是objective-c需要学习的基础语法

JavaScript DOM编程艺术学习笔记-第二章JavaScript语法

一.JavaScript示例 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8" /> 5 <title>Just a Test</title> 6 </head> 7 <body> 8 <script src="example.js"></scr

&lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第06章 | 抽象

第06章  抽象 ------ 懒惰即美德 假如要计算斐波那契数列(任何一个数是前两数之和的数字序列) >>> fibs=[0,1] >>> for i in range(8): fibs.append(fibs[-2]+fibs[-1]) #fibs[-2]+fibs[-1]后两位数,append往后添加 #运行后,包含10个斐波那契数列的10个数字是 >>> fibs [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 如果允许用户