零、 复习昨日
一、作业
二、向下转型
三、抽象
四、接口
final
- 修饰类,不能被继承
- 修饰方法,方法不能重写
- 修饰变量/属性, 变成常量
static
- static 修饰类(内部类),属性,方法
- 修饰的属性和方法,称为类属性,类方法,因为这些属性方法属于类不属于对象,也是因为静态属性和静态在内存只有一份,被该类的所有对象共享
- 静态属性和方法随类加载而初始化,所以它可以通过类名直接调用
- 静态方法只能调用静态方法和静态属性(静态只能调用静态)
- 静态方法内不能调用this
总结:static应用
当有些属性需要被共享时就设置static
当有些方法需要被频繁调用,为了方便使用,设置静态
综合使用
- 为经常配合final一起修饰常量, 静态常量
- public static final double PI = 3.1415926…;
- public static final 顺序无所谓,但是建议按public static final顺序
多态
- 是指方法执行出现的多态效果
- 前提
- 继承/实现
- 重写
- 向上转型(父类引用指向子类对象)
- Animal animal = new Dog();
- 编译看父类,运行看子类
应用场景:
方法参数列表设计成父类型参数,调用时传入子类对象
为了存储
同一大类型
的属性,将数组定义为父类型的数组,但是数组中存储的是子类对象方法的返回值类型是父类类型,返回值是子类类型
public static MyAnimal getInstance(){ return new MyCat(); // return new MyDog(); } public static void main(String[] args) { MyAnimal instance = getInstance( ); instance.eat(); }
设计一个合理的程序:有一个灯泡(Bulb)类.灯泡有发光的方法,
他有两个子类,分别是红灯泡和绿灯泡;
还有一个台灯(TableLamp)类,他有一个开灯的方法,实现开红灯,红灯亮,发红光,开绿灯,绿灯亮,发绿光;
public class Bulb {
public void light(){
System.out.println("灯泡发亮" );
}
}
public class RedBulb extends Bulb {
@Override
public void light() {
System.out.println("红灯泡,发红光");
}
}
package com.qf.homework2;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 台灯
*/
public class TableLamp {
public void open(Bulb bulb){
bulb.light();
}
// public void open(RedBulb redBulb){
// redBulb.light();
// }
// public void open(GreenBulb greenBulb){
// greenBulb.light();
// }
// public void open(PinkBulb pinkBulb){
// pinkBulb.light();
// }
public static void main(String[] args) {
// 买台灯
TableLamp tableLamp = new TableLamp( );
// 买灯泡
RedBulb redBulb = new RedBulb( );
GreenBulb greenBulb = new GreenBulb( );
PinkBulb pinkBulb = new PinkBulb( );
BlackBulb blackBulb = new BlackBulb( );
// 装入灯泡,开灯
tableLamp.open(blackBulb);
}
}
父类引用指向子类对象 : 向上转型
什么时候需要向上转型? 在需要使用多态效果时向上转型
向下转型: 只有先向上的父类引用才能向下转为子类对象
public static void main(String[] args) {
// 向上转型
Animal animal = new Dog();
animal.eat();
// 向下转型
// 类转换异常,报错ClassCastException
Dog dog = (Dog) new Animal();// 报错ClassCastException
Dog dog2 = (Dog) animal; // 正常,可以转换
}
为什么要向下转型?
- 当需要使用子类特有的方法时
public static void show() {
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
// 展示
for (int i = 0; i < animals.length; i++) {
Animal animal = animals[i];
animal.eat();
if (animal instanceof Dog) {
Dog dog = (Dog)animal;
dog.watchHome();
} else if (animal instanceof Cat) {
Cat cat = (Cat)animal;
cat.catchMouse();
}
}
}
}
抽象: 看不懂,看着不太像,不具体的看不明白
抽象类: 使用abstract修饰的类是抽象类 (抽象类中有的方法是抽象的看不懂…)
package com.qf.oop2;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
public abstract class Animal {
// 报错,属性不需要抽象
// abstract int age;
int age;
/**
* 1 抽象方法没有方法体
* 2 抽象方法需要使用abstract修饰
* 3 抽象方法需要放在抽象类中
* 4 抽象类需要使用abstract
* 5 抽象类中可以有正常方法
* 6 抽象类也可以没有抽象方法
* 7 抽象类中有构造方法,但是不能直接new对象
* 而是子类构造时会调用抽象父类构造方法,初始化父类对象
* 8 抽象类是用来被继承的
* --------------------
* 9 子类继承抽象类,要么子类也变成抽象类,
* 要么实现所有抽象方法
* 实现? 重写方法,让方法能真正的执行
*/
abstract void eat();
public void move(){
System.out.println("动物移动" );
}
public Animal(){
System.out.println("Animal()" );
}
}
之前练习的各种继承
多态
的题,父类方法都可以变成抽象方法和抽象类
练习: 改造灯泡练习题,将父类改造成抽象类和抽象方法即可
练习: 改造形状练习题,将父类改造成抽象类和抽象方法即可
总结: 抽象类应用就是一种
约束的效果
,是一种限制
,子类一旦继承父类,就必须要重写方法
用法总结:
- 使用到别人的抽象类,继承后要重写方法
- 当设计程序时,有些类需要被子类继承且必须重写方法时,就把父类设计成抽象
抽象类是用来抽象差异性、具体共同点的。也就是将差异性方法抽象化,提供给子类用于重写。共同的方法具体化,所有子类继承。
把子类不一样的方法抽象成抽象方法,每个子类都重写
把子类都一样的方法提取到父类,每个子类直接用,不用重写
引用数据类型: 数组,类,接口
接口不是类,比抽象类还抽象的一种java文件
接口不是类
,使用的interface修饰的接口中没有属性,
所有属性都是常量
,默认被public static final修饰接口中没有正常方法,
所有方法都是抽象
的,默认都被public abstract修饰接口中没有构造方法,
不能创建对象的
.接口主要是用来被子类
实现implements
子类实现接口,就
必须重写所有
抽象方法,否则就要将自己定义成抽象类子类允许
多实现
接口,用逗号隔开子类允许
继承的同时再实现
接口public class UDisk extends Electron implements USB , Disk{}
接口之间允许继承,且允许多继承(类不允许多继承)
与抽象类用处基本一致,用在多态的场景
USB use = new UDisk();
改造了灯泡类为接口
改造了形状为接口
接口是一种能力的体现
接口是一种规范/约定
接口即是设计:在设计层面,接口可以避免我们陷入对细节的过多思考,
可以让我们站在一个更高的视角对系统做更好的评估,比如系统的交互
设计是否合理,功能是否缺失,是否具备可行性,是否过于复杂等等。public boolean login(String username,String password);
接口即是约定:在编码层面,接口可以明确的告诉开发人员如何使用
(接口的语义,需要什么作为输入,会有什么输出),而开发人员只
需要根据这些约定去实现具体的功能代码即可。
对于以后写代码,该怎么设计?
- 很多类有公共的属性,方法的抽取成父类来继承
- 有些类中的方法被抽取到父类中,但是子类又不合适还需要重写,那就把类和方法定义成抽象
- 将一些功能性的行为定义成接口,让想拥有这些功能的类去实现即可
设计程序 :
电脑类的属性 : 有多个usb插口
电脑类的功能 :
1) 通过接口插入外设 (u盘,麦克风,键盘等)
2) 开机
要求: 电脑开机前,先启动外设
3) 关机
要求: 电脑关机前,先关闭外设
外设类(u盘,麦克风,键盘等)
功能 : 启动 关闭
USB接口
定义usb设备的统一功能
开启() 关闭()
效果 :
创建电脑对象,能插入外设,调用方法电脑开机,电脑开机前 外设启动,
电脑关机前,外设先关闭