多态 抽象类 接口
- 多态
1. 多态概述
2. 多态成员访问特点
3. 向上转型和向下转型
4. 存储特点 - 抽象类
1. 抽象类概述
2. 抽象类成员特点 - 接口
1. 接口概述
2. 接口成员特点
3. 抽象类与接口区别
1. 多态
-
多态概述:多态指的是同一个事物在不同环境下表现出来的状态
多态的优点:
提高代码扩展性
提高代码的维护性
多态的缺点:
无法使用子类中特有的功能class Animal{ } class Cat extends Animal{ } Cat cat1=new Cat(); Animal cat2=new Cat();
多态的前提:
- 必须有继承
- 子类必须有方法重写
- 父类引用指向子类对象
即 Animal cat2=new Cat();
Ps:采用多态写法时候,如果父类中的方法被子类重写,在调用的时候以子类重写后的方法为准
-
多态的成员访问特点
1:成员变量
编译看左边,运行看左边。
2:构造方法
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
3:成员方法
编译看左边,运行看右边。
4:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
总结:除了成员方法之外,其余编译和运行都看父类引用
public class MyTest {
public static void main(String[] args) {
//多态
//多态的形式去访问成员变量,访问的还是父类的成员变量
//编译看左边,运行看左边。
Fu fu=new Zi();
System.out.println(fu.num);
//多态的形式去调用方法时,编译看左边,运行看右边
fu.show();
//多态形式,调用静态方法,运行的是父类的静态方法
fu.test();
Fu.test();
Zi.test();
}
}
class Fu{
int num=10;
public Fu() {
System.out.println("父类构造执行了");
}
public void show(){
System.out.println("fu show");
}
public static void test() {
System.out.println("fu test");
}
}
class Zi extends Fu{
int num=666;
public Zi() {
System.out.println("子类构造执行了");
}
@Override
public void show() {
System.out.println("zi show");
}
public static void test() {
System.out.println("zi test");
}
}
3. 向上转型和向下转型
向上转型:
多态的本质其实是子类对象的向上转型,转至父类引用,因而在使用过程中无法使用子类特有功能,但是可以使用父类中的所有属性和方法,当父类方法被重写时,以子类被重写的方法为准。即将子类对象转换为父类对象,可以访问二者共有的属性和方法。
向下转型:
向下转型是指将已经向上转型的的对象再向下转型,即将指向父类引用改回指向子类引用,向下转型后与之前创建子类对象对子类进行实例化相同。向下转型之后相当于子类的一个对象,因此可以访问子类中特有的方法。
public class MyTest {
public static void main(String[] args) {
Animal an = new Cat(); //多态就是向上转型
an.eat();
Cat cat= (Cat) an; //向下转型 将父引用转换成子类
cat.catcheMouse();
System.out.println("------------------");
Dog dog = new Dog(); //创建子类对象,完成子类实例化
dog.eat(); //调用子类对象的方法
dog.lookDoor();
System.out.println("----------------------------");
Animal an2= new Dog(); //创建一个对象an2指向父类
an2.eat(); //调用an2和子类中共有的方法eat();
Dog d= (Dog) an2; //向下转型
d.lookDoor(); //调用子类特有方法
}
}
class Animal {
public void eat(){
System.out.println("吃饭");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void lookDoor(){
System.out.println("狗看门");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catcheMouse(){
System.out.println("猫抓老鼠");
}
}
- 存储特点
2. 抽象类
- 抽象类概述
抽象类指的是在父类中使用abstract修饰类和其中方法,使得子类必须对其抽象方法进行改写。
抽象类的特点:- 抽象类和抽象方法必须用abstract关键字修饰
抽象类格式: abstract class 类名 {}
抽象方法格式: public abstract void eat(); - 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类中可以有构造方法,抽象类不能进行实例化,
抽象类的构造方法的作用:
用于子类访问父类数据时的初始化 - 抽象类不能直接实例化那么,抽象类如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。 - 抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
- 抽象类和抽象方法必须用abstract关键字修饰
- 抽象类的成员特点:
- 成员变量:既可以是变量,也可以是常量。
- 构造方法:用于子类访问父类数据的初始化。
- 成员方法:既可以是抽象的,也可以是非抽象的。
- 抽象类的成员方法特性:
- 抽象方法 强制要求子类做的事情。
- 非抽象方法 子类继承的事情,提高代码复用性。
public class Test {
public static void main(String[] args) {
Workers worker1 = new Workers();
Workers worker2 = new Workers();
worker1.setID(5171122);
worker1.setName("小明");
worker1.setSalary(10000);
worker2.setID(5171133);
worker2.setName("小何");
worker2.setSalary(12000);
System.out.println("Worker1:");
worker1.work();
System.out.println(worker1.getName()+"---"+worker1.getID()+"---"+worker1.salary);
System.out.println("Worker2:");
worker2.work();
System.out.println(worker2.getName()+"---"+worker2.getID()+"---"+worker2.salary);
System.out.println("--------------------------");
Manager manager = new Manager();
manager.setID(11223344);
manager.setName("刘总");
manager.setSalary(20000);
manager.setPonus(10000);
System.out.println("Manager:");
manager.work();
System.out.println(manager.getName()+"---"+manager.getID()+"---"+manager.getSalary()+"---"+manager.getPonus());
}
}
abstract class Employee{
int ID;
String name;
int salary;
public abstract void work();
}
class Workers extends Employee{
int ID;
String name;
int salary;
public void work(){
System.out.println("Workers' work ");
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
class Manager extends Employee{
int ID;
String name;
int salary;
int ponus;
public void work(){
System.out.println("管理者的工作");
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getPonus() {
return ponus;
}
public void setPonus(int ponus) {
this.ponus = ponus;
}
}
3. 接口
- 接口概述:
接口:与类同级别,接口主要用来定义一些扩展额外的功能
Ps:接口不能实例化 - 接口的使用:
- 接口用关键字interface表示 格式: interface 接口名 {}
- 类实现接口用implements表示 格式: class 类名 implements 接口名 {}
- 接口不能实例化,但是可以通过多态的方式实例。
- 接口的子类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
- 接口的成员特点:
- 成员变量;只能是常量,并且是静态的。
默认修饰符:public static final
建议自己手动给出。 - 构造方法:接口没有构造方法。
- 成员方法:只能是抽象方法。
默认修饰符:public abstract
建议自己手动给出。
- 成员变量;只能是常量,并且是静态的。
- 类与类,类与接口,接口与接口的关系
- 类与类:
继承关系,只能单继承,可以多层继承。 - 类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。 - 接口与接口:
继承关系,可以单继承,也可以多继承。
- 类与类:
- 接口与抽象类的区别
- 成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象 - 设计区别
抽象类中定义的是子类共性的属性功能,子类再进行方法重写
接口中定义的是类的扩展的额外功能
- 成员区别
public class Test {
public static void main(String[] args) {
Cats cat1 = new Cats();
cat1.age=1;
cat1.name="猫1";
System.out.println(cat1.age+"---"+cat1.name);
cat1.eat();
cat1.sleep();
System.out.println("---------------");
Dogs dog1 = new Dogs();
dog1.age=1;
dog1.name="狗1";
System.out.println(dog1.age+"---"+dog1.name);
dog1.eat();
dog1.sleep();
System.out.println("---------------");
someCats cat2 = new someCats();
Cats cat=cat2;
cat.name="特猫";
cat.age=2;
cat2 = (someCats) cat;
Jump Jc=cat2;
cat2.sleep();
cat2.goodeat();
System.out.println(cat2.age+"+++"+cat2.name);
cat2.jump();
System.out.println("---------------");
someDogs dog2=new someDogs();
Dogs dog =dog2;
dog2.name="特狗";
dog2.age=2;
dog2=(someDogs) dog;
Jump Jd=dog2;
dog2.sleep();
dog2.goodeat();
System.out.println(dog2.age+"+++"+dog2.name);
dog2.jump();
}
}
abstract class Animal{
public String name;
public int age;
public void eat(){};
public void sleep(){};
}
class Cats extends Animal{
public String name;
public int age;
public void eat(){
System.out.println("猫吃鱼");
}
public void sleep(){
System.out.println("猫睡觉");
}
}
class Dogs extends Animal{
public String name;
public int age;
public void eat(){
System.out.println("狗啃骨头");
}
public void sleep(){
System.out.println("狗睡觉");
}
}
class someCats extends Cats implements Jump{
public void goodeat(){
System.out.println("这只猫吃千层面");
}
@Override
public void sleep(){
System.out.println("这只猫很能睡");
}
@Override
public void jump() {
System.out.println("猫跳得高");
}
public someCats() {
System.out.println("部分猫的特有的功能");
}
}
class someDogs extends Dogs implements Jump{
public void goodeat(){
System.out.println("这只狗吃狗粮");
}
@Override
public void sleep(){
System.out.println("这只狗很少睡觉");
}
@Override
public void jump() {
System.out.println("狗跳得高");
}
public someDogs() {
System.out.println("部分狗特有的功能");
}
}
interface Jump{
void jump();
}