首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

面向对象的编程-Application 5

Previously on OOP:

In Hello class, we can create an object of Calculation class and use dotted notation to invoke some of the methods in Calculation class. Furthermore, we switched to FirstExample project and worked on Person class. A Person has three attributes:SSN, name, and surname. In additional, we have also created a constructor for Person class incorporating value assignment of these three attributes.

下面,我们来编写一些Person类的methods。由于Person类的attributes前面的关键字都是“private”,也就是“私有的”,其他类使用object reference + dotted notation + attribute name都不能直接访问的。那么,要怎样才能取到或者修改attributes的值呢?在Java中有一类methods叫做getters and setters能实现。

为了尽可能少地引入getters and setters编码的错误,强烈建议使用Eclipse自带的功能来创建它们。在代码编写的区域内右击一次鼠标,接着依次选:source => generate getters and setters=>选择开发者需要的getters and setters(可以只选择一部分),就能被自动创建好,如下所示:

除了getters and setters之外,我们还可以编写一些其他的methods。

从功能上来看,init()函数和constructor相似,都是把接收到的参数的值分别赋予三个attributes。但是,constructor是在创建实例的时候调用的,这个函数却只能在实例创建之后,使用object reference + dotted notation + method name()来调用。

从编码方式上来看,constructor中使用了“this.”指针,由于参数的名称和attributes的名称相同。而init()函数的参数和attributes的名称是不同的,所以没有必要在attributes的前面加上“this.”指针。

第二个method是print()函数。

再看最后一行的“return this;”返回的是调用这个函数的object的指针,类型已经在函数头中写好了,是Person类型的。这种类型的返回值在Stream章节中比较常见,因为还可以把前面一个函数的返回值看做新的object reference,然后继续调用其他methods。至于在Person类中会有什么作用,会在后文中分析。

此外,“return this;”这样的返回值使得这个函数最好不要被命名为toString()。在Object类中,即所有类的父类,有一个函数是toString(),功能是把Object类的实例的名称和hash code转化为一个字符串。在本黄鸭印象中,toString()函数的返回值不是Object类,而是void类型,所以直接把print()函数的名称改成toString()并不能把这个函数视为toString()函数的overriding,所以还是不要改名为好。

第三个和第四个method分别是justTheName()和aDash()函数。

这两个函数的返回值和print()函数相同,但是justTheName()的功能是打印出name attribute的值,aDash()函数是给Person的实例赋予一套全新的attributes的值。

以上就是Person类中的所有methods。

接下来,我们新建一个PersonApp类,里面有一个main函数,再在main函数中创建Person的实例,并且用dotted notation来调用Person类里面的方法。

这个例子再次强调了创建一个Person类的实例分为三个步骤,第一步是创建一个空的Person类型的指针,第二步是用new关键字创建实例,第三步是把第二步的指针赋值给第一步的指针。这三个步骤往用一行代码全部搞定:

在这段代码的最后一行,我们使用Person类的实例的object reference,名称是“p”来调用print()函数。看print()函数是哪一个类的函数,应该看object是哪一个类,而不是object reference是哪一个类,因为object reference的类型可能是object的父类,根据polymorphism性质。此时,object和object reference全是Person类的,那么就理所当然地在Person类中寻找print()函数。

在这个例子中,Person类中是有print()函数的,如果没有,那么就要按照level of inheritance hierarchy找到Person类的父类,看父类中有没有print()函数。

调用print()函数的结果是在Eclipse的standard output中,打印出了一个一行字:GoldenDuck-LenovoGoldenDuck。

以Person类的代码和Person类的实例为基础,我们研究以下几个问题。第一个问题:在Java中是不是所有的数据全部必须调初始化?

在上面这段代码中,用object reference “p”调用了Person类的init()函数,把这个实例像在C语言中那样地初始化。首先,这一步是没有必要的,因为在调用constructor创建实例的时候,已经给attributes赋值了。

更近一步地说,Java语言中的变量都不需要人为地初始化,因为compiler自动会认为所有变量的初始值都是NULL。即便是constructor初始化失败了,那么调用print()函数打印出来的结果是NULL NULL NULL,不会是random characters。

于此不同的是,C语言和C++语言都特别强调变量的初始化。假如没有人为地初始化,那么变量中存放的内容是不可预知的,可能是NULL,可能是,可能是正确的值,更可能是乱码。

第二个问题:how to access in an external way to the data stored in another class?这个问题已经强调过很多遍了。第一点,尽量类的attributes全部都是“private”的,否则容易导致racing condition。第二点,private的成员变量在类的外部不能直接用dotted notation来访问,只能通过getters and setters这一类特殊的methods。

上面这段代码现在是不能工作的,除非在Person类中把所有的attributes都改成“public”的。有的人时常在这个时候会问:“protected”行不行?这是一个标准的visibility level的问题,只要找到protected关键字的visibility level的表格,问题就可以迎刃而解。当然,“protected”关键字在本课程中使用得很少,这里就不详细地分析了,供大家观后思考。

第三个问题:can several reference pointing to the same object?在理论部分我们已经讲过了这个问题,答案是yes,现在我们在实践中运用一下:

新建一个Person类型的指针,名称叫做samePerson。这个指针的命名遵守camelBack,即驼峰形规则,也就是首字母小写,然后好几个单词连在一起写,中间没有空格,只是从第二个单词开始,每个单词的首字母大写。首字母小写是为了避免与class的命名相同。

接着,我们把p的值赋给samePerson,这样p和samePerson指向的是同一个object,且不仅p可以被用来调用print()函数,用samePerson的效果也是一样的。

第四个问题:连续调用好几个函数是怎样的一种体验?这种情况在Stream中非常常见,我们先稍微体验一下,顺便学习一下应该怎样阅读OOP的代码。

在上面这段代码中,只有最后两行代码是连续调用了好几个函数的,本黄鸭重点分析一下最后一行代码,所以倒数第二行作为思考题。anotherPerson是一个Person类型的指针,调用了justTheName()函数,打印Person实例的name attribute,即Copper,并且返回和anotherPerson指针相同对象的指针,所以anotherPerson.justTheName()和anotherPerson都是指针,且指向的实例相同。

再调用aDash()函数,把CopperDuck-Lenovo重新赋值为GreenDuck-Lenovo,并返回和anotherPerson指针相同对象的指针。再用这个指针调用justTheName()函数,此时打印出来的是Green,并且返回和anotherPerson指针相同对象的指针。最后调用print()函数,打印出一行字:GreenDuck-Lenovo Green Duck。

Print()函数后面还能继续调用吗?答案是可以的,因为这个函数的返回值还是Person类型的this指针。

欢迎使用本黄鸭编写的小程序~

微信公众号二维码:

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180925G1AFC000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券