9. 面向对象 -- 多态、抽象、接口
来源:互联网 发布:港珠澳大桥 知乎 编辑:程序博客网 时间:2024/06/06 03:27
1:final关键字(掌握)
由于继承中方法有一个现象:方法重写。
所以,父类的功能,就会被子类给覆盖调。
有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
这个时候,针对这种情况,Java就提供了一个关键字:final
class Fu { public final void show() { System.out.println("这里是绝密资源,任何人都不能修改");//结果显示 }}class Zi extends Fu { //public void show() { // Zi中的show()无法覆盖Fu中的show() //System.out.println("这是一堆垃圾"); }class ZiDemo { public static void main(String[] args) { Zi z = newZi(); z.show(); }}
(1)final:最终的意思。常见的是它可以修饰类,方法,变量。
(2)特点:
A:final可以修饰类,该类不能被继承。
B:final可以修饰方法,该方法不能被重写。(覆盖,复写)
C:final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。
常量:A:字面值常量 "hello",10,true
B:自定义常量 finalint x = 10;
(3)面试题:
A:final修饰局部变量的问题
a:基本类型:基本类型的值不能发生改变。
b:引用类型:引用类型的地址值不能发生改变,但是对象的内容是可以改变的
class Student { int age = 10;}class FinalTest { public static void main(String[] args) { //局部变量是基本数据类型 int x =10; x = 100; System.out.println(x); //100 final int y = 10; //无法为最终变量y分配值 //y = 100; System.out.println(y); //10 System.out.println("--------------"); //局部变量是引用数据类型 Student s = newStudent(); System.out.println(s.age); //10 s.age = 100; System.out.println(s.age); //100 System.out.println("--------------"); final Student ss = new Student(); System.out.println(ss.age); //10 ss.age = 100; System.out.println(ss.age); //100 //重新分配内存空间(地址值) //无法为最终变量ss分配值 //ss = new Student(); }}
B:final修饰变量的初始化时机
a:被final修饰的变量只能赋值一次。
b:在构造方法完毕前。(非静态的常量)
c:常见的给值
定义的时候。(推荐)
构造方法中。
classDemo { //intnum = 10; //finalint num2 = 20; intnum; finalint num2; { //num2= 10; } publicDemo() { num= 100; //无法为最终变量num2分配值 //num2= 200; }}class FinalTest2 { publicstatic void main(String[] args) { Demod = new Demo(); System.out.println(d.num); System.out.println(d.num2); }}
2:多态(掌握)
(1)多态:同一个对象(事物),在不同时刻体现出来的不同状态。
(2)多态的前提:
A:要有继承关系。
B:要有方法重写。
其实没有也是可以的,但是如果没有这个就没有意义。
动物 d = new 猫();
d.show();
动物 d = new 狗();
d.show();
C:要有父类引用指向子类对象。
父 f = new 子();
(3)多态的分类:
a:具体类多态
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
b:抽象类多态
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
c:接口多态
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
(4)多态中的成员访问特点
A:成员变量 编译看左边,运行看左边
B:构造方法 创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法 编译看左边,运行看右边(由于成员方法存在方法重写,所以它运行看右边)
D:静态方法 编译看左边,运行看左边(静态和类相关,算不上重写,所以,访问还是左边的)
class Fu { publicint num = 100; publicvoid show() { System.out.println("showFu"); } publicstatic void function() { System.out.println("functionFu"); }}class Zi extends Fu { publicint num = 1000; publicint num2 = 200; publicvoid show() { System.out.println("showZi"); } publicvoid method() { System.out.println("methodzi"); } publicstatic void function() { System.out.println("functionZi"); }}class DuoTaiDemo { publicstatic void main(String[] args) { //要有父类引用指向子类对象。 //父 f = new 子(); Fuf = new Zi(); System.out.println(f.num); //100 成员变量 编译看左边,运行看左边 //System.out.println(f.num2); //找不到符号 f.show(); //show Zi 成员方法 编译看左边,运行看右边 //f.method(); //找不到符号 f.function(); //function Fu 成员方法编 译看左边,运行看右边 }}
(5)多态的好处:
A:提高代码的维护性(继承体现)
B:提高代码的扩展性(多态体现)
(6)多态的弊端:
父不能使用子的特有功能。
现象:子可以当作父使用,父不能当作子使用。
(7)我就想使用子类的特有功能?行不行?
行。
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)
对象间的转型问题:
向上转型:
Fu f = new Zi();
向下转型:
Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
class Fu { publicvoid show() { System.out.println("showfu"); }}class Zi extends Fu { publicvoid show() { System.out.println("showzi"); } publicvoid method() { System.out.println("methodzi"); }}class DuoTaiDemo4 { publicstatic void main(String[] args) { //测试 Fuf = new Zi(); f.show(); //f.method(); //父类中没有method()方法 //创建子类对象 //Ziz = new Zi(); //z.show(); //z.method(); //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢? //如果可以,但是如下 Zi z =(Zi)f; //(可以,但是很多时候不合理。向下转型,太占内存了) z.show(); z.method(); }}
(8)ClassCastException类型转换异常:一般在多态的向下转型中容易出现
class Animal { publicvoid eat(){}}class Dog extends Animal { publicvoid eat() {} publicvoid lookDoor() { }}class Cat extends Animal { publicvoid eat() { } publicvoid playGame() { }} class DuoTaiDemo5 { publicstatic void main(String[] args) { //内存中的是狗 Animala = new Dog(); Dogd = (Dog)a; //内存中是猫 a= new Cat(); Catc = (Cat)a; //向下转型 //内存中是猫 Dogdd = (Dog)a; //再次向下转型发生ClassCastException类型转换异常 }}
(9)多态的练习
A:猫狗案例
B:老师和学生案例
C:看程序写结果:先判断有没有问题,如果没有,写出结果
多态的成员访问特点:
方法:编译看左边,运行看右边。
继承的时候:
子类中有和父类中一样的方法,叫重写。
子类中没有父亲中出现过的方法,方法就被继承过来了。
class A { publicvoid show() { show2(); } publicvoid show2() { System.out.println("我"); }}class B extends A { publicvoid show2() { System.out.println("爱"); }}class C extends B { publicvoid show() { super.show(); } publicvoid show2() { System.out.println("你"); }}public class DuoTaiTest4 { publicstatic void main(String[] args) { Aa = new B(); a.show(); //爱 Bb = new C(); b.show(); //你 }}
3:抽象类(掌握)
(1) 一个没有具体的方法体的方法是抽象的方法。在一个类中如果有抽象方法,该类必须定义为抽象类。
(2)抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
因为它不是具体的。
抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
用于子类访问父类数据的初始化
D:抽象类的子类
a:如果不想重写抽象方法,该子类是一个抽象类。
b:重写所有的抽象方法,这个时候子类是一个具体的类。
抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
Animal a =new Cat();
//abstract class Animal //抽象类的声明格式abstract class Animal { //抽象方法 //publicabstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体 publicabstract void eat(); publicAnimal(){}}//子类是抽象类abstract class Dog extends Animal{} //子类是具体类,重写抽象方法class Cat extends Animal { publicvoid eat() { System.out.println("猫吃鱼"); }}class AbstractDemo { publicstatic void main(String[] args) { //创建对象 //Animal是抽象的; 无法实例化 //Animala = new Animal(); //通过多态的方式 Animala = new Cat(); a.eat(); }}
(3)抽象类的成员特点:
成员变量:既可以是变量,也可以是常量。
构造方法:有。用于子类访问父类数据的初始化。
成员方法:既可以是抽象的,也可以是非抽象的。
抽象类的成员方法特性:
A:抽象方法 强制要求子类做的事情。
B:非抽象方法 子类继承的事情,提高代码复用性。
abstract class Animal { publicint num = 10; publicfinal int num2 = 20; publicAnimal() {} publicAnimal(String name,int age){} publicabstract void show(); publicvoid method() { System.out.println("method"); }}class Dog extends Animal { publicvoid show() { System.out.println("showDog"); }}class AbstractDemo2 { publicstatic void main(String[] args) { //创建对象 Animala = new Dog(); a.num= 100; System.out.println(a.num); //a.num2= 200; System.out.println(a.num2); System.out.println("--------------"); a.show(); a.method(); }}
(4)抽象类的练习
A:猫狗案例练习
/*猫狗案例具体事物:猫,狗共性:姓名,年龄,吃饭分析:从具体到抽象猫:成员变量:姓名,年龄构造方法:无参,带参成员方法:吃饭(猫吃鱼)狗:成员变量:姓名,年龄构造方法:无参,带参成员方法:吃饭(狗吃肉)因为有共性的内容,所以就提取了一个父类。动物。但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,而方法是抽象的类,类就必须定义为抽象类。抽象动物类:成员变量:姓名,年龄构造方法:无参,带参成员方法:吃饭();实现:从抽象到具体动物类:成员变量:姓名,年龄构造方法:无参,带参成员方法:吃饭();狗类:继承自动物类重写吃饭();猫类:继承自动物类重写吃饭();*///定义抽象的动物类abstract class Animal {//姓名private String name;//年龄private int age;public Animal() {}public Animal(String name,int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//定义一个抽象方法public abstract void eat();}//定义具体的狗类class Dog extends Animal {public Dog() {}public Dog(String name,int age) {super(name,age);}public void eat() {System.out.println("狗吃肉");}}//定义具体的猫类class Cat extends Animal {public Cat() {}public Cat(String name,int age) {super(name,age);}public void eat() {System.out.println("猫吃鱼");}}//测试类class AbstractTest {public static void main(String[] args) {//测试狗类//具体类用法//方式1:Dog d = new Dog();d.setName("旺财");d.setAge(3);System.out.println(d.getName()+"---"+d.getAge());d.eat();//方式2:Dog d2 = new Dog("旺财",3);System.out.println(d2.getName()+"---"+d2.getAge());d2.eat();System.out.println("---------------------------");Animal a = new Dog();a.setName("旺财");a.setAge(3);System.out.println(a.getName()+"---"+a.getAge());a.eat();Animal a2 = new Dog("旺财",3);System.out.println(a2.getName()+"---"+a2.getAge());a2.eat();//练习:测试猫类(略)}}
B:老师案例练习
/*老师案例具体事物:基础班老师,就业班老师共性:姓名,年龄,讲课。分析:基础班老师姓名,年龄讲课。就业班老师姓名,年龄讲课。实现:老师类基础班老师就业班老师*///定义抽象的老师类abstract class Teacher {//姓名private String name;//年龄private int age;public Teacher() {}public Teacher(String name,int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//抽象方法public abstract void teach();}//基础班老师类class BasicTeacher extends Teacher {public BasicTeacher(){}public BasicTeacher(String name,int age) {super(name,age);}public void teach() {System.out.println("基础班老师讲解JavaSE");}}//就业班老师类class WorkTeacher extends Teacher {public WorkTeacher(){}public WorkTeacher(String name,int age) {super(name,age);}public void teach() {System.out.println("就业班老师讲解JavaEE");}}class AbstractTest2 {public static void main(String[] args) {//具体的类测试,自己玩//测试(多态)//基础班老师Teacher t = new BasicTeacher();t.setName("刘意");t.setAge(30);System.out.println(t.getName()+"---"+t.getAge());t.teach();System.out.println("--------------");t = new BasicTeacher("刘意",30);System.out.println(t.getName()+"---"+t.getAge());t.teach();System.out.println("--------------");//就业班老师t = new WorkTeacher();t.setName("林青霞");t.setAge(27);System.out.println(t.getName()+"---"+t.getAge());t.teach();System.out.println("--------------");t = new WorkTeacher("林青霞",27);System.out.println(t.getName()+"---"+t.getAge());t.teach();}}
C:学生案例练习
/*学生案例具体事务:基础班学员,就业班学员共性:姓名,年龄,班级,学习,吃饭分析:基础班学员成员变量:姓名,年龄,班级成员方法:学习,吃饭就业班学员成员变量:姓名,年龄,班级成员方法:学习,吃饭得到一个学员类。成员变量:姓名,年龄,班级成员方法:学习,吃饭实现:学员类基础班学员就业班学员*///定义抽象学员类abstract class Student {//姓名private String name;//年龄private int age;//班级private String grand;public Student() {}public Student(String name,int age,String grand) {this.name = name;this.age = age;this.grand = grand;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGrand() {return grand;}public void setGrand(String grand) {this.grand = grand;}//学习public abstract void study();//吃饭public void eat() {System.out.println("学习累了,就该吃饭");}}//具体基础班学员类class BasicStudent extends Student {public BasicStudent() {}public BasicStudent(String name,int age,String grand) {super(name,age,grand);}public void study() {System.out.println("基础班学员学习的是JavaSE");}}//具体就业班学员类class WorkStudent extends Student {public WorkStudent() {}public WorkStudent(String name,int age,String grand) {super(name,age,grand);}public void study() {System.out.println("就业班学员学习的是JavaEE");}}class AbstractTest3 {public static void main(String[] args) {//我仅仅测试基础班学员//按照多态的方式测试Student s = new BasicStudent();s.setName("林青霞");s.setAge(27);s.setGrand("1111");System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());s.study();s.eat();System.out.println("--------------");s = new BasicStudent("武鑫",48,"1111");System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());s.study();s.eat();//就业班测试留给自己玩}}
D:员工案例练习
/*假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。分析:普通员工类成员变量:姓名、工号以及工资。成员方法:工作经理类:成员变量:姓名、工号以及工资,奖金属性成员方法:工作实现:员工类:普通员工类:经理类:*///定义员工类abstract class Employee {//姓名、工号以及工资private String name;private String id;private int salary;public Employee() {}public Employee(String name,String id,int salary) {this.name = name;this.id = id;this.salary = salary;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}//工作public abstract void work();}//普通员工类class Programmer extends Employee {public Programmer(){}public Programmer(String name,String id,int salary) {super(name,id,salary);}public void work() {System.out.println("按照需求写代码");}}//经理类class Manager extends Employee {//奖金private int money; //bonus 奖金public Manager(){}public Manager(String name,String id,int salary,int money) {super(name,id,salary);this.money = money;}public void work() {System.out.println("跟客户谈需求");}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}}class AbstractTest4 {public static void main(String[] args) {//测试普通员工Employee emp = new Programmer();emp.setName("林青霞");emp.setId("czbk001");emp.setSalary(18000);System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());emp.work();System.out.println("-------------");emp = new Programmer("林青霞","czbk001",18000);System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());emp.work();System.out.println("-------------");/*emp = new Manager();emp.setName("刘意");emp.setId("czbk002");emp.setSalary(8000);emp.setMoney(2000);*///由于子类有特有的内容,所以我们用子类来测试Manager m = new Manager();m.setName("刘意");m.setId("czbk002");m.setSalary(8000);m.setMoney(2000);System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());m.work();System.out.println("-------------");//通过构造方法赋值m = new Manager("刘意","czbk002",8000,2000);System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());m.work();}}
(5)抽象类的几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
为了不让创建对象
C:abstract不能和哪些关键字共存
a: final 冲突
b: private 冲突
c: static 无意义
abstract class Fu { //publicabstract void show(); //非法的修饰符组合: abstract和private //privateabstract void show(); //非法的修饰符组合 //finalabstract void show(); //非法的修饰符组合 staticabstract void show(); publicstatic void method() { System.out.println("method"); }}class Zi extends Fu { publicvoid show() {}}class AbstractDemo3 { publicstatic void main(String[] args) { Fu.method(); }}
4:接口(掌握)
(1)回顾猫狗案例,它们仅仅提供一些基本功能。
比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,
是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。
(2)接口的特点:
A:接口用关键字interface修饰
interface 接口名 {}
B:类实现接口用implements修饰
class 类名 implements 接口名{}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
D:接口的实现类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)
(3)接口成员特点:
成员变量;只能是常量,并且是静态的。
默认修饰符:public static final 建议:自己手动给出。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法。
默认修饰符:public abstract 建议:自己手动给出。
所有的类都默认继承自一个类:Object。
类Object 是类层次结构的根类。每个类都使用 Object 作为超类。
(4)类与类,类与接口,接口与接口
A:类与类
继承关系,只能单继承,可以多层继承
B:类与接口
实现关系,可以单实现,也可以多实现。
还可以在继承一个类的同时,实现多个接口
C:接口与接口
继承关系,可以单继承,也可以多继承
(5)抽象类和接口的区别
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别:
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承:
C:设计理念不同
抽象类:被继承体现的是:”is a”的关系。 抽象类中定义的是该继承体系的共性功能。
接口: 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
- 9. 面向对象 -- 多态、抽象、接口
- 面向对象之抽象、接口、多态
- 面向对象(多态、抽象类、接口)
- 面向对象、多态、抽象类、接口
- java 面向对象 接口 抽象
- 面向对象---继承、抽象、接口
- 面向对象--继承、接口、抽象
- 黑马程序员-JAVA面向对象之抽象、接口、多态
- 面向对象4_【抽象类】【接口】【多态】
- 面向对象的继承、封装、多态、抽象、接口相关
- Java面向对象思想、类、抽象类、多态、接口
- JavaSE----面向对象(多态、抽象类、接口)
- 面向对象(多态,抽象类,接口的比较)
- Java面向对象(多态、抽象类、接口)
- 9 面向对象(final关键字,多态,抽象类,接口)
- 面向对象_多态_抽象类_接口
- Java面向对象_多态(抽象类、接口)巩固
- 面向对象_final关键字、多态、抽象类、接口总结
- 安装Ubuntu 16.04后要做的事
- java二维数组
- 云星数据---Scala实战系列(精品版)】:Scala入门教程022-Scala实战源码-Scala 多态01
- vue 循环出来的数据不能记录长度
- oracle 系统表空间满了
- 9. 面向对象 -- 多态、抽象、接口
- leetcode120 Triangle
- hrbust 病毒 并查集
- 判断二叉树是否是搜索二叉树和完全二叉树
- css设置元素水平垂直居中的方法
- eclipse如何重新编译项目
- Go Eclipse插件
- Hadoop之HDFS文件操作
- leetcode 134. Gas Station