一、面向对象特征—封装
引例
定义一个游戏中的英雄Hero类,属性有名字name、生命值life=[1-100]、和等级level=[1-菜鸟green hand,2-bronze,3-王者king]。
(1)战斗fight:减少双方的生命值:生命值 = 生命值 - 对方的攻击力 。攻击力 = 等级 ( 随机数10 +1 )
(2)战斗fght:使用绝招。绝招=[10-60],使用不同的绝招降低对方的生命值,但同时自己的生命值降低绝招的一半。
(3)输出英雄的信息。
类图:



从例子可以看出,对属性的可以随意修改和获取,如果需要保护属性,属性的值只读(不能修改)怎么办呢?
1.1 什么是封装
封装:将对象的状态信息隐藏在对象的内部,不允许外部程序直接访问对象的内部信息,通过该类提供的访问方法实现对内部信息的操作访问。
1.2 封装的步骤
1、修改属性的可见性 —将属性设为private。
2、创建getter/setter方法 —用于属性的读写
如果没有创建getter方法,属性不能读取,如果没有提供setter方法,属性就不能修改,这样就保护了属性。也就是在使用属性时必须调用getter/setter方法才能操作属性。

3、在getter/setter方法中加入属性控制语句 —对属性值的合法性进行判断
1.3 成员变量、成员方法与this关键字
1、成员变量(实例属性)
(1)对象的属性就是成员变量,它的作用域在类内部是全局的,即包括类的所有方法。
(2)当方法中局部变量和成员变量同名名,局部变量优先,即使用的是局部变量。
(3)在类里使用成员变量用this关键字修饰,如:this.成员变量。
2、成员方法(实例方法)
(1)对象的方法就是成员方法,调用类部方法可以用this关键字修饰,如:this.方法()。
1.4 类变量、类方法与static关键字
static修饰的变量和方法可以通过类名和对象名访问,而不用static修饰的变量和方法只能通过对象名访问。
1、类变量或静态常量:static修饰的属性称为类属性(类变量)

2、类方法:static修饰的方法称为类方法
1.5 方法的重载
方法的重载:指同一个类中多个方法:
- 方法名相同
- 参数列表不同(个数、顺序、类型三者只要有一项不同)
- 与返回值、访问修饰符无关
例:英雄战斗2种情况:
(1)战斗fight:减少双方的生命值:生命值 = 生命值 - 对方的攻击力 。攻击力 = 等级 ( 随机数10 +1 )
(2)战斗fght:使用绝招。绝招=[10-60],使用不同的绝招降低对方的生命值,但同时自己的生命值降低绝招的一半。
同是战斗,战斗的方式不一样,产生结果不一样。根据方法的参数不同,执行的结果也不一样的同一种行为,可以用方法的重载来解决。
1.6 构造方法
1、构造方法
用来实例化对象的方法,可在创建对象的同时给对象属性初始化。
- 方法名与类名相同
- 没有返回值项
- 可以指定参数 — 构造方法重载
public 构造方法名( ) {
//初始化代码
}

【练习】
1、根据类图写出类
(1)方法play():玩一次亲密度+20,健康值-10,健康值小于30,不能再玩了。
(2)方法feed():喂食一次健康值+20。
2、根据题1类图,重载玩的方法play(int n),玩飞盘,抓到一个飞盘,亲密度+5,健康值-20,健康值小于50,不能再玩了。
3、根据题1类图,重载2个构造方法:
(1)通过1个参数给昵称初始化,默认品种为拉不拉多,健康值为80,亲密度为50。
(2)通过4个参数分别给昵称、品种、健康值和亲密度初始化。
二、面向对象特征—继承
引例
根据类图写出类
(1)方法feed():喂食一次,亲密度+20,健康值+30。
(2)方法toString():输出宠物信息。
(3)方法play():dog玩一次亲密度+10,健康值-20。penguin捕鱼一次,亲密度-10,健康值-20。
代码略……
从以上例子可以看出,2个类有很很多相同的特征和行为,这样造成代码冗余。如果将相同的属性和方法抽取出来,进行优化设计,这样就可以减少代码冗余了。
2.1 什么是继承
继承:将具有相同属性和方法的类中相同属性和方法提取出,构建一个新类,这个新类就是父类,然后由父类再构建子类,子类继承父类的属性和方法,使得子类对象具有父类的特征和行为。
2.2 继承的步骤
1、编写父类

2、编写子类,继承父类


有些父类成员不能继承:
- private成员
- 子类与父类不在同包,使用默认访问权限的成员
- 构造方法
继承特性:
- 传递性:B类继承A类,C类继承B类,C类也继承A类的属性和方法。
-
2.3 super关键字
子类访问父类的成员使用super。
super():调用父类的构造方法。
- super.name:访问父类的属性。
- super.toString():访问父类的方法。
2.4 方法的重写
在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。
- 子类方法与父类方法具有相同的名字。
- 参数列表与父类方法相同。
- 返回值类型与父类方法相同。
- 子类方法访问权限不能比父类更严格。
例如:
(1)方法toString():输出宠物信息。
(2)方法play():dog玩一次亲密度+10,健康值-20。penguin捕鱼一次,亲密度-10,健康值-20。
toString()方法在父类中没有输出狗的品种和企鹅的性别。
如果需要输出狗的品种,在狗类(子类)中重写输出方法,同样,需要输出企鹅的性别,在企鹅(子类)中重写输出方法。
Dog子类重写toString()
Penguin子类重写toString()
play()方法在父类中只能写一种玩法,因为dog和penguin玩法不一样,写哪一种都不合适。所以在父类中没法实现算法,只有到各子类中去实现。
Dog子类重写play()
Penguin子类重写play()
2.5 抽象类、抽象方法和abstract关键字
1、抽象类
- 在继承关系中,去实例化一个父类没有意义,它的特征和方法无法确定,可以使用抽象类来限制父类被实例化,抽象类是不能被实例化的。
- 抽象类用关键字abstract来修饰。


2、抽象方法
父类的play方法,每个子类实现步骤都不一样,即方法体没有实际意义的语句,像这样的方法可以写成抽象方法。
- 抽象方法用abstract关键字修饰。
- 抽象方法没有方法体。
- 抽象方法必须在抽象类里。
- 抽象方法必须在子类中被实现。
2.6 final关键字
final关键字修饰的变量的值是最终的值,即不能修改它的值—常量。
final关键字修饰的方法为最终的方法—不能被重写。
final关键字修饰的类为最终的子类—不能被继承。
[练习]
4、某汽车租赁公司出租多种车辆,车型及租金情况如下:
编写程序实现计算租赁价。
分析:
(1)轿车类:属性:车牌号、品牌、车型。方法:计算租金(天数),计算租金(公里数)。
(2)客车类:属性:车牌号、品牌、座位。方法:计算租金(天数),计算租金(公里数)。
(3)由(轿车类,客车类)抽象父类机动车类。
三、面向对象特征—多态
引例
给宠物添加一个康复方法:
(1)狗狗康复:打针,健康值+50。
(2)Q仔康复:调养,健康值+30。
父类Pet:
子类Dog重写方法:
子类Penguin重写方法:
编写一个主人类,带Q仔和狗狗去治疗。

(3)假如认养了一只宠物猫,咪咪康复是吃药,健康值+30。
主人类又要重载一个治疗的方法:
是不是领养一只宠物就要重载一个治疗的方法?
频繁修改代码,代码可扩展性、可维护性差 。
可以使用多态来优化代码—解决代码的扩展性。
1.1 什么是多态
多态:不同类的对象对同一消息做出不同的响应。即不同对象在调用同一个方法时表现出多种不同的行为(同一个方法作出不同操作)。
如:狗狗对象、Q仔对象、咪咪对象在调用同一个方法时,表现的行为不一样:
如上例中,主人带宠物去玩也是多态,教师教授不同的课程也是多态,……。即同一种事物,由于条件不同,产生的结果不同。
1.2 多态的实现步骤
1、继承是多态的基础,没有继承就没有多态。
如:Dog、Penguin、Cat都继承了Pet。
2、子类重写父类的方法。
如:Pet类的play方法和recovered方法都是抽象方法,在子类必须重写。
3、父类指向子类的应用:
(1)父类 对象名 = new 子类();
(2)父类作为方法的参数
【练习】
5、用多态实现打印机
(1)黑白打印机打印试卷。
(2)彩色打印机打印照片。
6、超市双11打折规则:
水果类商品:
50<=总价,8折优惠
30<=总价<50,9折优惠
肉类商品:
100<=总价,8折优惠
50<=总价<100,9折优惠
7、求以下图形的面积和周长
| Shape(图形) | ||
|---|---|---|
| Circle(圆形) | Triangle(等边三角形) | Rectangle(矩形) |
| radius(半径) | base(底边) heigth(高) |
length(长) width(宽) |
| area()(面积) perimeter()(周长) |
area()(面积) perimeter()(周长) |
area()(面积) perimeter()(周长) |
8、用多态实现第4题。
创建一个租车人类,属性:租车(可以租多辆车不同类型的车),天数。
方法:租赁。

