面向对象的特点————多态
什么是多态呢:就是某一事物,在不同时刻表现出来的不同的状态,也就是说,
Cat c=new Cat();
Animal a=new Cat();
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。动物 d = new 猫();
多态的前提:
1.要有继承关系
2.要有方法重写
3.要有父类引用指向子类对象
例如:
public class demo92 {
public static void main(String[] args) {
Perso an = new Studen();
an.sleep();
an.eat();
an.show();
}
}
class Perso{
public void eat(){
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
public void show() {
System.out.println("我爱学习");
}
}
class Studen extends Perso{
@Override
public void eat() {
System.out.println("我爱吃肉");
}
@Override
public void sleep() {
System.out.println("我睡觉喜欢听歌");
}
}
多态中的成员访问特点:
1.以多态的形式来访问成员变量 使用的还是父类的变量(编译看左边,运行也看左边)
2.多态的形式访问成员方法 编译看左边,运行看右边
3.多态形式访问构造方法:创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
4.多态形式访问静态方法:编译看左边,运行看左边
来看下面的代码:
public class MyTest {
public static void main(String[] args) {
Father f = new Zi();
System.out.println(f.num);
f.show();
f.car();
}
}
class Father{
int num = 1;
public void show(){
System.out.println("父亲的钱");
}
public static void car(){
System.out.println("父亲的汽车");
}
}
class Zi extends Father{
int num=2;
@Override
public void show() {
System.out.println("儿子的钱");
}
public static void car() {
System.out.println("儿子的汽车");
}
}
输出结果:
1
儿子的钱
父亲的汽车
多态的好处:
1.提高了代码的维护性
2.提高了代码的扩展性
多态的弊端:
1.不能使用子类特有的功能,这时就要我们向下转
Cat cat = new Cat();
Animal an=cat;
Cat c= (Cat) an; //向下转型
public class MyTest3 {
public static void main(String[] args) {
Sun sun = new Sun();
Father an=sun;
an.eat();
Sun s=(Sun)an;
s.basketball();
//s=new Doughter();转型异常ClassCastException
Doughter doughter = new Doughter();
an=doughter;
an.eat();
((Doughter) an).sing();
}
}
class Father{
public void eat(){
System.out.println("吃饭");
}
}
class Sun extends Father {
@Override
public void eat() {
System.out.println("爱吃烤串");
}
public void basketball(){
System.out.println("回打篮球");
}
}
class Doughter extends Father {
@Override
public void eat() {
System.out.println("爱吃米饭");
}
public void sing(){
System.out.println("会唱歌");
}
}
多态的内存图解
抽象类的学习
抽象类用来描述一种类型应该具备的基本特征与功能,具体如何完成这些行为由子类通过重写去完成。比如说汽车都会拉东西,但属于汽车的用途不同,所以汽车只定义了来东西的功能,但不知道都拉什么东西,拉多少,所以这些细节就交给货车,小轿车去具体实现。
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。既它只有功能声明,没有功能主体实现的方法。
抽象类的定义:
//抽象类格式: abstract class 类名 {}
//抽象方法格式: public abstract void eat()
public abstract class Employee{
public abstract void work();
}
class Teache extends Employee{
@Override
public void work() {
System.out.println("正在上班");
}
}
class Manager extends Employee {
@Override
public void work() {
System.out.println("正在开会");
}
}
抽象方法的使用
1.抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
2.抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么用呢?用于子类访问父类数据时的初始化。
3.抽象类不能进行实例化,可按照多态的方式,由具体的子类实例化。
4.抽象类的子类要么是抽象类,要么重写抽象类中的所有的抽象方法
5.一个类如果没有抽象方法,可以定义为一个抽象类,不能创建对象
6.abstract不能和 private,final,static共存,因为他们不能被继承
假如我们在开发一个系统时需要对员工(Employee)类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。
经理(Manager)也是员工,除了含有员工的属性外,另为还有一个奖金(bonus)属性。
public class MyTest {
public static void main(String[] args) {
Person p= new Employee();
p.name="王五";
p.number=10;
p.slary=3000;
System.out.println(p.name+"=="+p.number+"=="+p.slary);
p.work();
Person s= new Manager();
s.name="张麻子";
s.number=30;
s.slary=100000;
((Manager) s).bonus=300;
System.out.println(s.name+"==="+s.number+"==="+s.slary);
s.work();
}
}
abstract class Person{
public String name;
public int number;
public double slary;
public abstract void work();
}
class Employee extends Person {
@Override
public void work() {
System.out.println("员工996");
}
}
class Manager extends Person {
public double bonus;
@Override
public void work() {
System.out.println("老板在开会");
}
}
接口的概述&及其特点
为了体现事物功能的扩展性,java中提供了接口来定义额外的功能,但是并不给出具体实现。
如果一个类中只是由抽象方法和全局常量所组成,那么在这种情况下不会为其定义一个抽象类,而只会将其定义为接口,所以所谓的接口严格来讲就属于一个特殊的类,而且这个类中只有抽象方法与全局常量
使用:
1.接口用关键字interface表示 interface 接口名{}
2.类实现接口用implements表示 class 类名 implements 接口名{}
3.接口不能直接实例化,我们可以用多态的方式来实例化
4.接口的子类可以是抽象类,也可以是具体类,但是要重写接口中所有的抽象方法
抽象类
public abstract class Person {
public abstract void eat();
public abstract void sleep();
}
接口
public interface Kaiinterface {
public abstract void drive();
}
子类一
public class Teacher extends Person implements Kaiinterface{
@Override
public void eat() {
System.out.println("喜欢吃扯面");
}
@Override
public void sleep() {
System.out.println("晚上睡得早");
}
@Override
public void drive() {
System.out.println("老师是个老司机");
}
}
子类二
public class Student extends Person implements Kaiinterface {
@Override
public void drive() {
System.out.println("刚学会开车");
}
@Override
public void eat() {
System.out.println("喜欢吃辣片");
}
@Override
public void sleep() {
System.out.println("晚上睡得迟");
}
}
测试类
public class MyTest {
public static void main(String[] args) {
Teacher teacher = new Teacher();
Person an = teacher;
an.eat();
an.sleep();
Teacher s = (Teacher) an;
s.drive();
Student student = new Student();
an=student;
an.eat();
an.sleep();
Student p=(Student)an;
((Student) an).drive();
}
}
接口成员的特点
成员变量:只能是常量,并且是静态的。默认修饰符:public static final(建议手动给出)
构造方法:接口没有构造方法
成员方法:只能是抽象的方法,默认public abstract
JDK1.8之后接口中,可以定义默认方法,可以有方法的具体实现,需要在void前加default
类与类,类与接口,接口与接口的关系
类与类 | 继承关系,只能单继承,可以多层继承 |
---|---|
类与接口 | 实现关系,可以单实现,也可以多实现,并且还可以在继承一个类的同时实现多个接口 |
接口与接口 | 继承关系,可以单继承,也可以多继承 |
抽象类与接口的区别
成员变量 | 构造方法 | 成员方法 | |
---|---|---|---|
抽象类 | 可以是变量,也可以是变量 | 有 | 可以抽象,也可以非抽象 |
接口 | 只可以是常量 | 无 | 只可以抽象 |
也可以这样理解,抽象类被继承体现的是:“is a”的关系,它里面定义的是该继承体系的共性功能。接口,体现的是:“like a”的关系,接口中定义的是该继承体系的扩展功能。