09.01_多态的概述及其代码体现
- A:多态(ploymorphic)概述
- 事物存在的多种形态
- B:多态前提
- a:要有继承关系
- b:要有方法重写
- c:要有父类引用指向子类的对象
- C:案例演示
- 代码体现多态
class Demo1_Ploymorphic { public static void main(String[] args) { Animal a = new Cat(); //父类引用指向子类对象 a.eat(); //输出:猫吃鱼 } } class Animal { public void eat() { System.out.println("动物吃饭"); } } //继承关系 class Cat extends Animal { public void eat() { //方法重写 System.out.println("猫吃鱼"); } }
09.02_多态中的成员访问特点——成员变量
- A:案例演示
class Demo2_Polynorphic {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
System.out.println(f.num); //输出:10
}
}
class Father {
int num = 10;
}
class Son extends Father {
int num = 20;
}
-
B:内存图解
-
C:总结
- 编译看左边(父类),运行看左边(父类)
09.03_多态中的成员访问特点——成员方法
- A:案例演示
class Demo2_Polynorphic {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
f.print(); //son
}
}
class Father {
int num = 10;
public void print() {
System.out.println("father");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("son");
}
}
-
B:内存图解
-
C:总结
- 编译看左边(父类),运行看右边(子类)
- 编译的时候,看父类中有无该方法,若没有,则编译就通不过;运行的时候,调用的就是子类的方法。
09.04_多态中的成员访问特点——静态成员方法
- A:案例演示
class Demo2_Polynorphic {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
f.method(); //father static method.静态方法只与类相关,相当于Father.method();
}
}
class Father {
int num = 10;
public void print() {
System.out.println("father");
}
public static void method() {
System.out.println("father static method");
}
}
class Son extends Father {
int num = 20;
public void print() {
System.out.println("son");
}
public static void method() {
System.out.println("son static method");
}
}
- B:总结
- 编译看左边(父类),运行看左边(父类)
- 静态和类相关,算不上重写,所以访问还是左边的
- 只有非静态的成员方法,编译看左边,运行看右边
09.05_理解多态的案例——超人的故事
- A:故事叙述
- 某商人特有钱,有一天到五角大楼找一哥们谈生意。谈生意的过程中,看到有一个人跳楼。然后这哥们说要去救人,商人就问,你凭什么救人,这哥们说,他自己是超人。商人又问,你怎么证明你是超人,这哥们说,稍等一下。于是这哥们换了一套超人服装,飞出去把人救了。
- B:程序实现
class Demo1_SuperMan {
public static void main(String[] args) {
Person p = new SuperMan(); //父类引用指向子类对象,超人提升为人(因为一般情况下,超人是以普通人身份出现)
System.out.println(p.name); //John.普通人的名字
p.business(); //谈几个亿的大单
//p.fly(); //会报错。因为父类里没有fly方法
}
}
//超人有难的时候才会出现,所以平常就是个普通人
class Person {
String name = "John";
public void business() {
System.out.print("谈生意");
}
}
class SuperMan extends Person {
String name = "superMan";
public void business() {
System.out.print("谈几个亿的大单");
}
public void fly() {
System.out.print("飞出去救人");
}
}
09.06_多态中的向上转型和向下转型
- A:案例演示
class Demo1_SuperMan {
public static void main(String[] args) {
Person p = new SuperMan(); //父类引用指向子类对象,就是向上转型
System.out.println(p.name);
p.business();
SuperMan sm = (SuperMan)p; //向下转型
sm.fly();
}
}
//父类
class Person {
String name = "John";
public void business() {
System.out.print("谈生意");
}
}
//子类
class SuperMan extends Person {
String name = "superMan";
public void business() {
System.out.println("谈几个亿的大单");
}
public void fly() {
System.out.println("飞出去救人");
}
}
- B:格式
- 向上转型:Person p = new SuperMan();
- 向下转型:SuperMan sm = (SuperMan)p;
- C:内存图解
09.07_多态的好处和弊端
- A:多态的好处
- a:提高代码的维护性(继承保证)
- b:提高代码的扩展性(多态保证)
- B:案例演示
- 多态的好处
- 可以把父类对象当作形式参数,用以接收任意子类对象。
- 多态的好处
- C:弊端
- 不能使用子类的特有属性和行为
- D:案例演示——不带多态
class Demo1_Animal {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
//若再添加其他类,则又要重载method方法,扩展性很差。
}
public static void method(Cat c) {
c.eat();
}
public static void method(Dog d) {
d.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("看家");
}
}
- E:案例演示——带多态
class Demo1_Animal {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
}
public static void method(Animal a) { //当作参数的时候用多态最好,因为扩展性强
//关键字 instanceof 判断前边的引用是否是后边的数据类型
if (a instanceof Cat) {
Cat c = (Cat)a;
c.eat();
c.catchMouse();
}else if (a instanceof Dog) {
Dog d = (Dog)a;
d.eat();
d.lookHome();
}else {
a.eat();
}
}
}
class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("看家");
}
}
09.08_多态中的题目分析
- A: 程序段1
class Test1_Polynorphic {
public static void main(String[] args) {
Fu f = new Zi();
f.method(); //会报错,因为父类里没有method方法
f.show();
}
}
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
- B: 程序段2
class Test1_Polynorphic {
public static void main(String[] args) {
A a = new B();
a.show(); //爱
B b = new C(); //你。B类里其实有show方法,因为B类可以从A类里继承show方法
b.show();
}
}
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
09.09_抽象类的概述及其特点
- A:抽象类概述
- 抽象就是看不懂的
- B:抽象类特点
- a:抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名 {}
- public abstract void eat();
- b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
- c:抽象类不能实例化,那么,抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- d:抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法。
- a:抽象类和抽象方法必须用abstract关键字修饰
- C:案例演示
class Demo1_Abstract {
public static void main(String[] args) {
//Animal a = new Animal(); //错误:Animal是抽象的,无法实例化
Animal a = new Cat(); //父类引用指向子类对象
a.eat();
}
}
abstract class Animal { //抽象类
public abstract void eat(); //抽象方法
}
class Cat extends Animal { //重写抽象类中的所有抽象方法
public void eat() {
System.out.println("猫吃鱼");
}
}
09.10_抽象类的成员特点
- A:抽象类的成员特点
- a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?答案是不能。
- b:构造方法:有
- 用于子类访问父类数据时的初始化。
- c:成员方法
- 既可以是抽象的,也可以是非抽象的
- B:抽象类的成员方法特性
- a:抽象方法:强制要求子类做的事情
- b:非抽象方法:子类继承的事情,提高代码的复用性
- C:案例演示
class Demo1_Abstract {
public static void main(String[] args) {
}
}
abstract class Demo {
int num1 = 10;
final int num2 = 20;
public Demo() {}; //抽象类构造函数
public void print() { //抽象类里可以使用非抽象方法,这样子类可以直接继承使用,不必重写
System.out.println("111");
}
public abstract void method(); //抽象方法,子类必须对其进行重写
}
class Test extends Demo {
public void method() { //子类必须重写抽象父类里的抽象方法
System.out.println("111");
}
}
09.11_抽象类练习——猫狗案例
- A:案例演示
- 具体事物:猫,狗
- 共性:姓名,年龄,吃饭
- 猫的特性:抓老鼠
- 狗的特性:看家
- B:程序段
class Test1_Abstract {
public static void main(String[] args) {
Cat c = new Cat("加菲",8);
System.out.println(c.getName()+ "..." + c.getAge());
c.eat();
c.catchMouse();
Dog d = new Dog("八公",30);
System.out.println(d.getName() + "..." + d.getAge());
d.eat();
d.lookHome();
}
}
abstract class Animal {
private String name;
private int age;
public Animal() {} //无参
public Animal(String name,int age) { //有参
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public abstract void eat(); //吃饭,抽象类,在下面具体类里必须重写
}
class Cat extends Animal {
public Cat() {}
public Cat(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public Dog() {}
public Dog(String name,int age) {
super(name,age);
}
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("看家");
}
}
09.12_抽象类练习——老师案例
- A:案例演示
- 具体事物:基础班老师,就业班老师
- 共性:姓名,年龄,讲课
- B:程序段
class Test1_Teacher {
public static void main(String[] args) {
BaseTeacher bt = new BaseTeacher("冯佳",18);
bt.teach();
}
}
abstract class Teacher {
private String name;
private int age;
public Teacher() {} //无参
public Teacher(String name,int age) { //有参
this.name = name;
this.age = age;
}
public void setName(String name) { //设置姓名
this.name = name;
}
public String getName() { //获取姓名
return name;
}
public void setAge(int age) { //设置年龄
this.age = age;
}
public int getAge() { //获取年龄
return age;
}
public abstract void teach();
}
class BaseTeacher extends Teacher {
public BaseTeacher() {} //无参
public BaseTeacher(String name,int age) { //有参
super(name,age);
}
public void teach() {
System.out.println("我的姓名是:" + this.getName() + ",我的年龄是:" + this.getAge() + ",将的内容是java基础");
}
}
09.13_抽象类练习——员工案例
- A:案例演示
- 具体事物:假如我们在开发一个系统时需要对程序员类进行设计,程序员包含三个属性:姓名、工号及工资。经理,除了含有程序员的属性外,另外还有一个奖金属性。
- 请使用继承的思想设计出程序员类和经理类,要求类中提供必要的方法进行属性访问。
- B:程序段
class Test1_Employee {
public static void main(String[] args) {
Coder c = new Coder("德玛西亚","007",8000);
c.work();
Manager m = new Manager("苍老师","9527",3000,20000);
m.work();
}
}
abstract class Employee {
private String name;
private String id;
private double salary;
public Employee() {};
public Employee(String name,String id,double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
public abstract void work();
}
class Coder extends Employee {
public Coder() {};
public Coder(String name,String id,double salary) {
super(name,id,salary);
}
public void work() {
System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() + ",我的工资是:"
+ this.getSalary() + ",我的工作内容是敲代码");
}
}
class Manager extends Employee {
private int bonus;
public Manager() {};
public Manager(String name,String id,double salary,int bonus) {
super(name,id,salary);
this.bonus = bonus;
}
public void work() {
System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() + ",我的工资是:"
+ this.getSalary() + "我的奖金是:" + bonus + ",我的工作内容是管理");
}
}
09.14_抽象类中的面试题
-
A:面试题1
- 一个抽象类中如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
- 可以。这么做的目的只有一个,那就是不让其他类创建本类对象,交给子类完成。
- 一个抽象类中如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
-
B:面试题2
- abstract不能和哪些关键字共存?
- abstract和static
- 被abstract修饰的方法没有方法体
- 被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的。
- abstract和final
- 被abstract修饰的方法强制子类重写
- 被final修饰的不让子类重写,所以他俩矛盾。
- abstract和private
- 被abstract修饰的是为了让子类看到并强制重写
- abstract和static
public Manager() {};
public Manager(String name,String id,double salary,int bonus) {
super(name,id,salary);
this.bonus = bonus;
}public void work() {
System.out.println(“我的姓名是:” + this.getName() + “,我的工号是:” + this.getId() + “,我的工资是:”- this.getSalary() + “我的奖金是:” + bonus + “,我的工作内容是管理”);
}
}
- abstract不能和哪些关键字共存?
# 09.15_抽象类中的面试题
* A:面试题1
* 一个抽象类中如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以。这么做的目的只有一个,那就是不让其他类创建本类对象,交给子类完成。
* B:面试题2
* abstract不能和哪些关键字共存?
* abstract和static
* 被abstract修饰的方法没有方法体
* 被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的。
* abstract和final
* 被abstract修饰的方法强制子类重写
* 被final修饰的不让子类重写,所以他俩矛盾。
* abstract和private
* 被abstract修饰的是为了让子类看到并强制重写
* 被private修饰不让子类访问,所以他俩矛盾