多态polymorphim
ONE.多态的概述和访问特点
1.多态的概述
A:多态polymorphism:同一个对象在不同时刻体现出来的不同状态。
举例:
猫是猫,猫是动物
水(液态,气态,固态)
B:多态的前提:
a:要有继承关系
b:要有方法重写(没有不会报错,但是没有意义)
c:要有父类引用子类对象
格式:Fu f = new Zi();读法,把子对象引用给Fu类型的f
2.多态的成员访问特点;
A:成员变量:编译看左边,运行看左边
B:构造方法:创建子类对象时,要访问子类的构造方法,要先对父类进行数据初始化。
C:静态方法:编译看左边,运行看左边(这里就能证明前面提到,静态方法算不上方法重写。)
D:成员方法:编译看左边,运行看右边(这里用前面提到对继承的理解就很容易解释,Animal a = new Cat();a.show()。从右往左读,把Cat()对象引用给Animal型的a,所以要现在Animal类中找到show()方法,这个方法被重写,所以来到子类中找到这个show()使用,如果Anima类中根本没有这个show()方法,从最开始就不会进行下去)
class Fu{
int num = 10;
public Fu(){}
public void show(){
System.out.println("show fu");
}
public static void method(){
System.out.println("show static fu");
};
}
class Zi extends Fu{
int num = 20;
public Zi(){}
public void show(){
System.out.println("show zi");
}
public static void method(){
System.out.println("show static zi");
}
}
class PolymorphismDemo{
public static void main(String[] args){
Fu f = new Zi();
System.out.println(f.num);
f.show();
f.method();
}
}
/*
输出结果
10
show zi
show static fu
*/
TWO.多态的优缺点和多态的转型
1.多态的优点
以一个动物类作为案例,引入动物操作类,
public static void useAnimal(Animal a){
a.sleep();
a.eat();
这个代码使用多态的特点,把父类和子类的关系,变成了好像变量一样,动物变量a的值可以取猫,狗,或者是动物本身。这样就能对类进行简化操作。
/*
动物类案例
父类动物类
子类狗类
子类猫类
方法操作类(创建这个类是为了解决在能够一次性调用猫类或者狗类全部方法的问题。)
测试类
*/
class Animal{
public Animal(){}
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep");
}
}
class Dog extends Animal{
public Dog(){}
public void eat(){
System.out.println("狗吃肉");
}
public void sleep(){
System.out.println("狗睡觉");
}
}
class Cat extends Animal{
public Cat(){}
public void eat(){
System.out.println("猫吃鱼");
}
public void sleep(){
System.out.println("猫睡觉");
}
}
class AnimalTools{
private AnimalTools(){}
public static void useAnimal(Animal a){
a.sleep();
a.eat();
}
}
class PolymorphismDemo2{
public static void main(String[] args){
Cat c = new Cat();
Cat c2 = new Cat();
Dog d = new Dog();
Dog d2 = new Dog();
/*这里创建了两只猫,两只狗,但如果接下来调用方法时就要出现重复的劳动,我们可以创建一个工具类,来代替这一操作*/
AnimalTools.useAnimal(c);
AnimalTools.useAnimal(c2);
AnimalTools.useAnimal(d);
AnimalTools.useAnimal(d2);
}
}
2.多态的弊端和多态的转型
A:多态的弊端:显然是使用多态的时候,是无法使用子类特有的方法的。
B:这个问题能不能解决呢?
那么这就涉及到了多态中的转型问题
a:向上转型
Fu f = new zi();
从右往左读,继承关系是从子类到父类,是向上的。
要注意的是,向上转型的两个类要有继承关系。
b:向下转型
Zi z = (Zi)f;
从右往左读,继承关系是从父类到子类,是向下的。
要注意的是:被强制类型转换的f必须是能够转化成zi类型的,说明f必须是通过向上转型得到的
class Animal{
public void eat(){
System.out.println("eat");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("dog eat meat");
}
public void look(){
System.out.println("dog look door");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("cat eat fish");
}
public void play(){
System.out.println("cat play woolen yarn");
}
}
class PolymorphismDemo3{
public static void main(String[] args){
Animal a = new Dog();
a.eat();
//a.look();报错
Dog d = (Dog)a;
d.eat();
d.look();
System.out.println("---------------");
a = new Cat();
a.eat();
//a.play();报错
Cat c = (Cat)a;
c.eat();
c.play();
}
}
/*
演示错误的内容
Dog dd = new Animal(); 编译报错,左右两边类型不一致,也不符合向上转型。从右到左不是向上转型,动物不一定是狗。
Dog ddd = new Cat(); 编译报错,左右两边类型不一致,也不符合向上转型。左右没有继承关系,猫不是狗。
Dog dd = (Dog)a;注意这里编译不报错,因为不运行不知道a是什么类型。但是运行报错,原因是a这里是猫不是狗。
*/
继承的内存图解
多态的内存图解
抽象类abstract
ONE.抽象类概述
1.抽象类的引入
前面学习中常常使用的猫狗案例,我们常常是将猫狗的父类动物类作为一个具体的类,并且这个类的成员方法也给了具体的功能。
实际上,动物一个大的范畴,比起猫狗,更具备概念属性。
由此引出一个新的概念抽象类
2.抽象类的定义和特点
A:抽象类的类名和抽象方法必须要用abstract来修饰。
抽象方法:没有方法体的方法叫抽象方法
abstract void show();这叫没有方法体,是抽象方法
abstract void show(){};这里是方法体为空,不是抽象方法
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类。
C:抽象类不能实例化,即抽象类不能通过创建对象来调用,毕竟是设计成一个抽象的概念,而创建对象是一个实例化的过程。那么抽象类有没有构造方法呢?答案是有的。抽象类的构造方法是用于子类访问父类进行数据初始化,,所以抽象类的可以通过多态的方式来进行具体的实例化。
D:抽象类的子类可以是一个具体类,这种情况下它必须重写父类的抽象方法;也可以是一个抽象类,这种情况下不用重写父类的抽象方法,也无法重写父类的抽象方法(抽象方法没有方法体)
abstract class Animal{
public abstract void show();
public void method(){
System.out.println("method");
}
}
abstract class Dog extends Animal{
}//当子类也是抽象类时,不会报错,要注意的是,不要忘记这个子类也是抽象类要受到抽象类的限制
class Cat extends Animal{
void show(){
System.out.println("show cat");
}
}
class AbstractDemo{
public static void main(String[] args){
Animal a = new Cat();//抽象类实例化要通过多态的方式
a.show();
a.method();
//Dog d = new Dog();报错,Dog是抽象的,无法实例化
}
}
3.抽象类员工案例
/*
员工类:
成员变量:姓名 工号 薪水salary
成员方法:敲代码
普通员工;
经理:
成员变量:姓名 工号 薪水 奖金bonus
成员方法:和客户谈项目
*/
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 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(int salary){
this.salary = salary;
}
public int getSalary(){
return 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("programmers type code");
}
}
class Manager extends Employee{
private int bonus;
public Manager(){}
public Manager(String name,String id,int salary,int bonus){
super(name,id,salary);
this.bonus = bonus;
}
public void setBonus(int bonus){
this.bonus = bonus;
}
public int getBonus(){
return bonus;
}
public void work(){
System.out.println("manager talks to others");
}
}
class AbstractTest4{
public static void main(String[] args){
Employee e = new Programmer();
e.setName("罗海威");
e.setId("ox0001");
e.setSalary(39999);
System.out.println(e.getName()+","+e.getId()+","+e.getSalary());
Manager m = new Manager("罗海威","ox0001",39999,49999);
System.out.println(m.getName()+","+m.getId()+","+m.getSalary()+","+m.getBonus());
}
}