目录
7.1 类的封装
封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其级体就是类本节将谭福介绍如何将类封装。
举一个简单的例子:我到一个餐馆去吃饭,点了一盘香辣肉丝,感觉很好吃,我就想知道厨师的名字,希望让厨师再为我多做点事情。
例7.1
package Leiduixiang; //包名
public class Restaurant1 { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
String cookName="Tom Cruise"; //厨师的名字叫Tom Cruise
System.out.println("**请让厨师为我做一份香辣肉丝。***"); //让厨师为我做一份香辣肉丝
System.out.println(cookName+"切葱花"); //让厨师切葱花
System.out.println(cookName+"洗蔬菜"); //让厨师洗蔬菜
System.out.println(cookName+"开始烹饪"+"香辣肉丝"); //厨师开始烹饪香辣肉丝
System.out.println("**请问厨师叫什么名字?***"); //厨师叫什么名字?
System.out.println(cookName); //输出厨师的名字
System.out.println("**请让厨师给我切一点葱花。***"); //让厨师给我切一点葱花
System.out.println(cookName+"切葱花"); //让厨师切葱花
}
}
所有的逻辑代码全是在main方法中实现的,代码完全暴露,我可以任意删改。如果能随意修改代码,就无法正常运作。为防止其他人修改厨师行为将厨师单独封装成一个类,将厨师的工作定义成厨师类的行为。
System.out.println("**请让厨师给我切一点葱花。***");
System.out.println(cookName+"搅鸡蛋"); //被乱改之后
System.out.println("**请让厨师为我做一份清蒸鱼。***");
System.out.println(cookName+"你是我的小呀小苹果~");//被乱改之后
如何防止其他人修改厨师的行为呢?就是将厨师打包成类。
例7.2
package Leiduixiang;
public class Restaurant2 { //创建类
public static void main(String[] args) { //主方法
// TODO Auto-generated method stub
cook1 cook=new cook1(); // 创建厨师类的对象
System.out.println("**请让厨师为我做一份香辣肉丝。***"); //输出信息
cook.cooking("香辣肉丝"); // 厨师烹饪香辣肉丝
System.out.println("**你们的厨师叫什么名字?***"); //输出**你们的厨师叫什么名字?***
System.out.println(cook.name); // 厨师回答自己的名字
System.out.println("**请让厨师给我切一点葱花。***"); //输出**请让厨师给我切一点葱花。***
cook.cutOnion(); // 厨师去切葱花
}
}
class cook1{ //创建Cook1类
String name; // 厨师的名字
public cook1() { //普通类
this.name="Tom Cruise"; // 厨师的名字叫Tom Cruise
}
void cutOnion() { //输出厨师切葱花
System.out.println(name+"切葱花"); //输出厨师切葱花
}
void washvegetables() { // 厨师洗蔬菜
System.out.println(name+"洗蔬菜"); //输出厨师洗蔬菜
}
void cooking(String dish) { // 厨师烹饪顾客点的菜
washvegetables(); //洗蔬菜
cutOnion(); //切葱花
System.out.println(name+"开始烹饪"+dish); //输出name + "开始烹饪" + dish
}
}
将厨师单独封装成一个类,将厨师的工作定义成厨师类的行为,当我们想让厨师做菜,只能道过调用对象成员方法的方式实现,而我们却不知道这个方法到底是怎么写的,所以就无法随意修改了。餐馆没有义务告诉我们厨师的任何信息,并且厨师也不会随意受我们差遣,所以说厨师有些属性和行为是不予公开的。
例7.3
package Leiduixiang; //类包
public class zy { //创建类
public static void main(String[] args) { //主方法
cook2 cook=new cook2(); //创建类
System.out.println("**请让厨师为我做一份香辣肉丝。***"); //输出请让厨师为我做一份香辣肉丝
cook.cooking("香辣肉丝"); //输出香辣肉丝
System.out.println("**你们的厨师叫什么名字?***"); //输出你们的厨师叫什么名字?
System.out.println(cook.name); //输出厨师的名字
System.out.println("**请让厨师给我切一点葱花。***"); //输出请让厨师给我切一点葱花
cook.cutOnion(); // 厨师去切葱花
}}
class cook2{ //创建类
private string name; // 厨师的名字
public cook2() { //创建Cook2()
this.name="Tom Cruise"; // 厨师的名字叫Tom Cruise
}
private void cutOnion() { // 厨师切葱花
System.out.println(name+"切葱花"); //输出Tom Cruise切葱花
}
private void washVegetables() { // 厨师洗蔬菜
System.out.println(name+"洗蔬菜"); //Tom Cruise洗蔬菜
}
void cooking(String dish) { // 厨师烹饪顾客点的菜
washVegetables(); //洗蔬菜
cutOnion() ; //切洋葱
System.out.println(name+"开始烹饪"+dish); // 输出厨师烹饪顾客点的菜
}
}
例7.4
package Leiduixiang; //类包
public class Restaurant4 { //创建类
private cook2 cook=new cook2(); //创建厨师类的对象
private void takeOrder(String dish) { //下单
cook.cooking(dish); //通知厨师做菜
System.out.println("你的菜好了,请慢用."); //输出你的菜好了,请慢用
}
public String saySorry() { //拒绝顾客请求
return"抱歉,餐厅不提供此项服务."; //输出抱歉,餐厅不提供此项服务
}
public static void main(String[] args) { //主方法
Restaurant4 water=new Restaurant4(); //创建新数组
System.out.println("**请让厨师为我做一份香辣肉丝。***"); //输出请让厨师为我做一份香辣肉丝
water.takeOrder("鱼香肉丝"); //服务员给顾客下单
System.out.println("**请问厨师叫什么名字?***"); //输出请问厨师叫什么名字
System.out.println(water.saySorry()); //服务员给顾客善意的答复
System.out.println("**请让厨师给我切一点葱花。***"); //输出请让厨师给我切一点葱花
System.out.println(water.saySorry()); //服务员给顾客善意的答复
}
}
从这个例子我们就能看出,作为顾客,我始终是和服务员进行交流,再由服务员与厨师进行交流整个过程中,顾客与厨师是完全没有交集的。作为顾客,我不知道我品尝的美食是由哪位厨师用何种方法烹任出来的,这种编程模式,就是封装。
将对象的属性和行为封装起来的载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。
7.2 类的继承
继承在面向对象开发思想中是一个非常重要的概念,它使整个程序架的具有一定的单色,在程
序中复用已经定义完善的类不仅可以减少软件开发周期,还可以提高软件的可能也都于程
本节将详细讲解类的继承。
在第6章中曾简要介绍过继承,其基本思想是基于某个父类的扩展,制定出一个新的子类,子类可以继承父类原有的属性和方法,也可以增加原来父类所不具备的属性和方法,或者直接重写又类中的某些方法。例如,平行四边形是特殊的四边形,可以说平行四边形类继束了四边形类,这时平行四边形类将所有四边形具有的属性和方法都保留下来,并基于四边形类扩展了一些新的平行四边形类特有的属性和方法。
下面演示一下继承性。创建一个新类Test,同时创建另一个新类Test2继承 Test类,其中包括重写的父类成员方法(重写的概念将在下文中详细介绍)以及新增成员方法等。在图7.5中描述了类Test与Test2的结构以及两者之间的关系。
7.2.1 extends 关键字
在Java中,让一个类继承另一个类,用extends关键字,语法如下:
child extends parents
这里child这个类作为子类继承了parents 这个类,并继承parents中的属性和方法。
child extends parents
举一个简单的例子:每个人都用过计算机,最常见的计算机就是台式机。后来随着科技的发展,计算机变得越来越小,台式机改良成了可移动的笔记本电脑,笔记本电脑又改良成了更轻薄的平板电脑。我们可以把普通计算机看成一个类,那么笔记本电脑和平板电脑都是这个类衔生出的子类。
例7.5
class Computer {//父类:电脑
String screen = "液晶显示屏"; //定义初值
void startup() { //返回参数
System.out.println("电脑正在开机,请稍等…"); //输出电脑正在开机,请等待...
}
}
public class Pad extends Computer { //父类:电脑
String battery ="5000毫安电池"; //子类独有属性
public static void main(String[] args) { //主方法
Pad pc = new Pad(); //电脑类
System.out.println("computer的屏幕是: " + pc.screen); //输出computer的屏幕是
pc.startup(); //返回参数
Pad ipad = new Pad(); //平板电脑类
System.out.println("pad的屏幕是:"+ ipad.screen); //子类可以直接使用父类属性
System.out.println("pad的电池是:"+ ipad.battery); //子类独有的属性
ipad.startup(); //子类可以直接使用父类方法
}
}
7.2.2 方法的重写
1.重写的实现
继承并不只是扩展父类的功能,还可以重写父类的成员方法。重写(还可以称为覆盖)就是在子类中将父类的成员方法的名称保留,重新编写成员方法的实现内容,更改成员方法的存储权限,或是修改成员方法的返回值类型(重写父类成员方法的返回值类型是基于J2SE 5.0版本以上编译器提供的新功能)。在继承中还有种特殊的重写方式, 子类与父类的成员方法返回值、 方法名称、参数类型及个教完全相同,唯一不同的是方法实现内容,这种特殊重写方式被称为重构。
子类重写父类的方法还可以修改方法的返回值类型,但这只是在J2SE 5.0以上的版本中支持的面功能,但这种重写方式需要遵循一个原则,即重写的返回值类型必须是父类中同一方法返回值关主的子类。
例7.6
class Computer2 { //创建类
void showPicture() { //显示图片
System.out.println("鼠标单击"); //输出鼠标单击
}
}
public class Pad2 extends Computer2{ //子类:平板电脑
void showPicture() { //显示图片
System.out.println("手指点击触摸屏"); //输出手指点击触摸屏
}
public static void main(String[] args) { //主方法
Computer2 pc = new Computer2(); //电脑类
System.out.print("pc打开图片: "); //输出PC打开图片
pc.showPicture(); //调用方法
Pad2 ipad = new Pad2(); //平板电脑类
System.out.print("ipad打开图片:"); //输出ipad打开图片
ipad.showPicture(); //重写父类方法
Computer2 computerpad = new Pad2(); //父类声明,子类实现
System.out.print("computerpad打开图片:"); //输出computerpad打开图片
computerpad.showPicture(); //调用父类方法,实现子类重写的逻辑
}
}
从这个结果我们可以看出,虽然子类调用了父类的方法,但实现的是子类重写后的逻辑, 而不是父类原有的逻辑。如果父类声明的对象是由子类实例化的,那么这个对象所调用的方法也是被子类重写过的。
2.super 关键字
如果子类重写了父类的方法,就再也无法调用到父类的方法了吗?如果想在子类的方法中实现父类原有的方法怎么办?为了解决这种需求,Java 提供了super 关键字。
super关键字的使用方法与this关键字类似。this 关键字代表本类对象,super 关键宇代表父类对象。使用方法如下:
super.property; //调用父类的属性
super.method(); //调用父类的方法
例7.7
class Computer3{ //创建类
String sayHello() { //定义一个方法
return "欢迎使用"; //返回一个字符串
}
}
public class Pad3 extends Computer3{ //子类:平板电脑
String sayHello() { //重写方法
return super.sayHello() +"平板电脑"; //调用父类方法,在其结果后添加字符串
}
public static void main(String[] args) { //主方法
Computer3 pc = new Computer3(); //电脑类
System.out.println(pc.sayHello()); //调用父类的方法并输出
Pad3 ipad = new Pad3(); //平板电脑类
System.out.println(ipad.sayHello()); //调用子类的方法并输出
}
}
7.2.3 所有类的父类——Object类
在开始学习使用class关键字定义类时,就应用了继承原理,因为在Java中,所有的类都直接或间接继承了java.lang.Object 类。Object 类是比较特殊的类,它是所有类的父类,是Java类层中的最高层类。当创建一一个类时,总是在继承,除非某个类已经指定要从其他类继承,否则它就是从java.lang.Object类继承而来的,可见Java中的每个类都源于java.lang.Object 类,如String、Integer 等类都是继承于Object类;除此之外自定义的类也都继承于O