Day09目标:
-
理解抽象方法、抽象类的应用场景;
-
掌握抽象方法、抽象类的语法;
-
理解接口的应用场景;
-
掌握接口的语法、应用;
-
掌握引用类型数组的用法;
-
代码量:课上120行,课下240行。
抽象类和接口
抽象类
设计规则
-
适合初学者:共3点
-
将子类共有的属性和行为,抽到父类 —— 抽取共性的
-
若子类的行为或代码和父类都一样,设计普通方法;若子类的行为或父类代码和父类不一样,设计为抽象方法。
-
???
-
抽象方法、抽象类
Animal类:
public class Animal {
String name;
int age;
String color;
Animal(){
}
Animal(String name, int age, String color){...}
}
喝水方法(行为都一样 —— 普通方法)
void drink() {
System.out.println(color + "色的" + age + "岁的" + name + "正在喝水");
}
吃饭方法(行为不一样 —— 抽象方法)
void eat() {
System.out.println(color + "色的" + age + "岁的" + name + "正在吃饭");
}
-
由abstract修饰,只有方法的定义,没有具体的实现(连{}都没有)
- 包含抽象方法的类必须是抽象类,抽象类由abstract修饰
Animal类
public abstract class Animal { // 不完整
String name;
int age;
String color;
Animal(){
}
Animal(String name, int age, String color){...}
}
void drink(){
System.out.println(color + "色的" + age + "岁的" + name + "正在喝水");
}
abstract void eat(); // 不完整,因为没有方法体
- 抽象类不能被实例化(new对象)—— 单独存在没有意义
Animal animal = new Animal(); // 编译错误
- 抽象类是需要被继承的
abstract class Animal{
name, age, color
void drink(){}
abstract void eat();
}
class Dog extends Animal{ // 编译错误
}
class Chick extends Animal{
}
-
抽象类是需要被继承的,子类:
-
也声明为抽象类
-
重写所有方法 —— 变不完整为完整
-
abstract class Animal{
name, age, color
void drink(){...}
abstract void eat();
}
class Dog extends Animal{
void eat(){
System.out.println(color + "色的" + age + "岁的狗狗" + name + "正在吃骨头!")
}
}
class Chick extends Animal{
System.out.println(color + "色的" + age + "岁的小鸡" + name + "正在吃小米!");
}
设计抽象方法的原因
-
真实的项目都是团队协作完成的
-
假设不设计抽象方法:
-
张光设计Dog类,吃的方法名称为eat()
-
李林设计Chick类,吃的方法名称为eating()
-
赵亮设计Fish类,吃的方法名称为ate()
-
孙其想让动物们吃饭 —— 需要记3个名字,还得与动物对应 → 麻烦
-
-
假设设计抽象方法eat表示吃:
-
张光设计Dog类,吃的方法只能叫eat(),必须重写
-
李林设计Chick类,吃的方法只能叫eat(),必须重写
-
赵亮设计Fish类,吃的方法只能叫eat(),必须重写
-
孙其想让动物们吃饭 —— 需要记1个名字,不用区分动物 → 方便
-
-
抽象类的意义
-
封装共有的属性和行为 —— 实现代码复用
-
可以包含抽象方法:
-
为子类提供统一的入口(名字统一)
-
强制必须重写
-
接口
设计规则
-
适合初学者:共3点(新老交替)
-
将所有子类共有的属性和行为,抽到父类中 —— 抽共性
-
若子类的行为/代码都不一样,设计普通方法;若子类的行为/代码不一样,设计抽象方法
-
将部分子类有共有的行为,抽到接口中
-
接口的应用
-
在现有案例基础之上,添加如下需求:
-
狗会游泳
-
鱼会游泳
-
鸡不会游泳
-
-
我们之前将父类理解成“亲爹”,而现在可以把接口理解成“干爹”。接口一般表示为:“具备某种功能”。
-
接口的应用:
-
接口是对继承单根性(单一继承)的扩展 —— 实现多继承
-
接口是一种标准、规范,表述具备某种功能。实现了某接口就具备某个功能,不实现接口就不具备那个功能。
-
接口的语法
-
接口是一种引用数据类型
-
由interface定义
-
目前内容而言,只能包含抽象方法(之后讲常量、默认方法、静态方法、私有方法)
interface Inter {
abstract void show();
void test(); // 接口中的方法默认都是抽象的,前面已经默认有abstract了
// void say(){} // 抽象方法不能有方法体
}
- 接口不能被实例化(new对象)
Inter o = new Inter(); // 编译错误,接口不能被实例化
- 接口是需要被实现的,实现类必须重写接口中的所有抽象方法。注意:重写接口中的方法时必须加public。
interface Inter{
abstract void show();
void test();
}
class InterImpl implements Inter{
public void show(){
}
public void test(){
}
}
接口的特点
-
一个类可以实现多个接口,以逗号分隔
-
若又继承又实现时,必须先继承后实现
interface Inter1{
void show();
}
interface Inter2{
void test();
}
abstract class Aoo{
say();
}
class Boo extends Aoo implements Inter1, Inter2{
@Override
public void show();
@Override
public void test();
@Override
void say(); // 前面public可写可不写
}
- 接口可以继承接口
interface Inter3{
void show();
}
interface Inter4 extends Inter3{
void test();
}
class Coo implements Inter4{
public void test(){}
public void show(){}
}
(类与类 —— 继承)
(接口与接口 —— 继承)
(类与接口 —— 实现)
引用类型数组
什么是引用类型数组?
-
引用类型数组:数组元素为引用类型的数组
-
存储10名学生:
Student[] student = new Student[10];
-
存储3只小狗:
Dog[] dogs = new Dog[3];
声明Dog
型数组,包含3个元素;每个元素都是Dog
类型,默认值为null
-
存储5辆汽车:
Car[] cars = new Car[5];
-
引用类型数组特点
-
引用类型数组与基本类型数组,有两点区别:
- 给引用类型数组的元素赋值时,需要new个对象
int[] arr = new int[3]; // 基本类型数组 arr[0] = 100; Dog[] dogs = new Dog[3]; // 引用类型数组 ——— 创建Dog数组对象 dogs[0] = new Dog("小黑", 2, "黑"); // 创建Dog对象
- 访问引用类型数组元素的属性/行为时,需要打点访问
Dog[] dogs = new Dog[3]; dogs[0] = new Dog("小黑", 2, "黑"); dogs[1] = new Dog("小白", 1, "白"); dogs[2] = new Dog("小灰", 3, "灰"); // 输出第一只狗狗的名字 System.out.println(dog[0].name); // 第3只狗狗游泳 dogs[2].swim(); 属性:name、age、color 行为:eat()、drink()、lookHome()、swim()