java-继承 多态 抽象

来源:互联网 发布:蓝牙车载充电器 知乎 编辑:程序博客网 时间:2024/06/04 19:00

引言
我们都知道,面向对象三大特点是,封装、继承和多态。所谓封装在前面的总结中已有所体现,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。那么,后面我将总结剩下的两个重要特点,继承和多态。
继承
通过extends关键字可以实现类与类的继承
格式:
class 子类名 extends 父类名 {
}
父类:基类,超类
子类:派生类
继承的好处:
A:提高了代码的复用性
多个类相同的成员可以放到同一个类中
B:提高了代码的维护性
如果功能的代码需要修改,修改一处即可
C:让类与类之间产生了关系,是多态的前提
说到继承,还有一个小的知识点需要掌握:
方法重写(子类的方法名,参数和父类完全一样,将父类方法覆盖):
1.必须存在继承关系
2.父类的方法满足不了你的需求,此时你就需要重写父类的方法,实现自己想要实现的功能
继承的特点:
A:Java只支持单继承,不支持多继承。
B:Java支持多层(重)继承(继承体系)。
什么时候使用继承呢?
继承中类之间体现的是:”is a”的关系。
可以举一个很简单的例子:
学生类:
成员变量:name,age
构造方法:无参,带参
成员方法:getXxx()/setXxx(),eat(),sleep()
老师类:
成员变量:name,age
构造方法:无参,带参
成员方法:getXxx()/setXxx(),eat(),sleep()
学生和老师可以提取出他们共有的部分写一个父类(人类):
人类:
成员变量:name,age
构造方法:无参,带参
成员方法:getXxx()/setXxx(),eat(),sleep()
学生类和老师类同时继承人类就好了。
相应的代码实现如下:

//父类public class Person {    private String name;    private int 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 Person(String name, int age) {        super();        this.name = name;        this.age = age;    }    public Person(){}}//学生类继承人类public class Student extends Person{    public Student(){}    public Student(String name,int age){        setName(name);        setAge(age);    }}//老师类继承人类public class Teacher extends Person{    public Teacher(){}    public Teacher(String name,int age){        setName(name);        setAge(age);    }}

类的组成:
成员变量
构造方法
成员方法
继承间的成员变量关系:
A:名字不同,非常简单。
B:名字相同
首先在子类局部范围找
然后在子类成员范围找
最后在父类成员范围找(肯定不能访问到父类局部范围)
如果还是没有就报错。(不考虑父亲的父亲…)
就近原则。
怎么去访问父亲的成员呢?
java就提供了一个关键字:super
super:super代表父类存储空间的标识(可以理解为父类对象)
this和super的使用区别?
A:成员变量
this.成员变量 本类的成员变量
super.成员变量 父类的成员变量
B:成员方法
this.成员方法() 本类的成员方法
super.成员方法()父类的成员方法
需求:请在show方法中输出40,30,20,10

package com.stu06;//请在show方法中输出40,30,20,10class Fu {    public int num = 10;    }class Zi extends Fu {    public int num2 = 20;    public int num = 30;        public void show() {        int num = 40;        System.out.println(num);        System.out.println(this.num);        System.out.println(num2);        System.out.println(super.num);      }}class ExtendsDemo5 {    public static void main(String[] args) {        Zi z  = new Zi();        z.show();    }}

编译运行后结果如下:
40
30
20
10
继承间的成员方法关系:
A:方法名不同,非常简单
B:方法名相同
首先在子类中找
然后在父类中找
如果还是没有就报错。(不考虑父亲的父亲…)
继承间构造方法的关系:
子类中所有的构造方法默认都会访问父类中空参数的构造方法(super())。因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
每个子类的构造方法的第一行,有一条默认的语句:super();
注意:仅仅是完成数据的初始化,创建对象目前必须用new申请空间。
假如父类没有无参构造方法,调用父类的其他构造方法。带参构造。
怎么访问呢?
super(…)
注意:
super(…)或者this(….)必须出现在第一条语句上。
因为如果可以放后面的话,就会对父类的数据进程多次初始化。所以,只能放在第一条语句上。
建议:
永远给出无参构造方法。
举一个继承的例子:
水果案例继承版
苹果:
成员变量:品种,颜色,价格
构造方法:有参无参
成员方法:getXxx()/setXxx();
show()
橘子:
成员变量:品种,颜色,价格
构造方法:有参无参
成员方法:getXxx()/setXxx();
show()

package com.stu01;//父类,fruitpublic class Fruit{    private String type;    private String color;    private int price;    public Fruit(){}    public Fruit(String type,String color,int price){        this.type =type;        this.color =color;        this.price =price;    }    public void setType(String type){        this.type =type;    }    public String getType(){        return type;    }    public void setColor(String color){        this.color =color;    }    public String getColor(){        return color;    }    public void setPrice(int price){        this.price =price;    }    public int getPrice(){        return price;    }    public void show(){        System.out.println(type+"  "+color+"  "+price);    }}package com.stu01;//苹果继承父类public class Apple extends Fruit{    public Apple(){}    public Apple(String type,String color,int price){        setType(type);        setColor(color);        setPrice(price);    }}package com.stu01;//橘子继承父类public class Orange extends Fruit{    public Orange(){}    public Orange(String type,String color,int price){        setType(type);        setColor(color);        setPrice(price);    }}package com.stu01;//测试类public class Test {    public static void main(String[] args) {        Apple a=new Apple("红富士","红色",20);        a.show();        o.setType("蜜橘");        o.setColor("黄色");        o.setPrice(12);        o.show();    }}

编译运行结果为:
红富士 红色 20
蜜橘 黄色 12
多态
多态:同一个对象,在不同时刻表现出来的不同状态。
举例:

水(液态)
冰(固态)
水蒸气(气态)
多态的前提:
A:有继承关系
B:有方法重写(不是必要条件,但是只有有了方法重写多态才有意义)
C:有父类引用指向子类对象
Fu f = new Zi();
左边: Fu类型的引用
右边:Fu类型的对象
成员访问特点
A:成员变量
编译看左边,运行看左边
B:构造方法
子类构造默认访问父类的无参构造
C:成员方法
编译看左边,运行看右边
为什么变量和方法不一样呢?
方法重写。
D:静态成员方法
编译看左边,运行看左边
因为静态的内容是和类相关的,与对象无关。
举一个简单的例子:

package com.stu06;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");    }}class DuoTaiTest {    public static void main(String[] args) {        Fu f = new Zi();        //f.method();        f.show();    }}   

f.method();这句话在程序编译过程中会报错,原因是什么呢?就像前面所说,成员方法在访问过程中,编译看左边,运行看右边,在子类中我们可以看到有method方法,但是在父类中并没有定义method方法,因此编译失败,去掉后的运行结果如下:
zi show
上面介绍的只是多态的一种,其实多态分为三种类型:普通泪多态,抽象类多态,接口类多态。下面分别介绍一下。
抽象类
抽象类特点:
A:抽象类和抽象方法必须用abstract关键字修饰
B:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
C:抽象类不能实例化
那么,如果实例化并使用呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
D:抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
抽象类的作用:
强制要求子类必须要重写某些方法。
抽象类的成员:
成员变量:可以是变量,也可以是常量。
构造方法:有构造方法,但不能实例化,用于子类访问父类数据的初始化。
成员方法:既可以是抽象的,也可以是非抽象的。
举一个抽象类的例子:
老师案例
具体事物:基础班老师,就业班老师
共性:姓名,年龄,讲课。
具体的代码实现如下:

//父类,teacherpublic abstract class Teacher {    private String name;    private int age;    public Teacher(){}    public Teacher(String name,int age){        this.age =age;        this.name=name;    }    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 show();}//基础班老师继承父类public class BasicTeacher extends Teacher{    public BasicTeacher(){}    public BasicTeacher(String name,int age){        setName(name);        setAge(age);    }    @Override    public void show() {            System.out.println("基础班老师讲基础课");        }    }    //就业班老师继承父类public class JobTeacher extends Teacher{    @Override    public void show() {        System.out.println("就业班老师讲就业课");        }    public JobTeacher(){}    public JobTeacher(String name,int age){        setName(name);        setAge(age);    }}//写一个测试类public class Test {    public static void main(String[] args) {        Teacher bt=new BasicTeacher();        bt.show();        Teacher jt=new JobTeacher("老师",25);        jt.show();        System.out.println(jt.getName()+" "+jt.getAge());    }}

编译运行后结果为:
基础班老师讲基础课
就业班老师讲就业课
老师 25
接口
类实现接口代表着这个类自身功能的一种扩展,所以接口代表着一种扩展的能力。
接口的特点:
A:定义接口要用关键字interface表示
格式:interface 接口名 {}
B:类实现接口用implements表示
格式:class 类名 implements 接口名 {}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
D:接口的实现类
要么是抽象类
要么重写接口中的所有抽象方法
多态的前提:
A:有继承或者实现关系
B:有方法重写
C:有父类引用或者父接口引用指向子类或者实现类对象
接口的成员特点:
A:成员变量
只能是常量。
默认修饰符:public static final
B:构造方法
没有构造方法
C:成员方法
只能是抽象方法。
默认修饰符:public abstract
下面强调一下接口、抽象类、类之间的关系以及区别:
A:成员区别
抽象类:
成员变量:可以是变量,也可以是常量
构造方法:有构造方法
成员方法:可以是抽象方法,也可以是非抽象方法
接口:
成员变量:只能是常量。默认修饰符 public static final
成员方法:只能是抽象方法。默认修饰符 public abstract
B:关系区别
类与类:
继承关系。只能单继承,可以多层(重)继承。
类与接口:
实现关系。可以单实现,也可以多实现。
还可以在继承一个类的同时实现多个接口
接口与接口:
继承关系。可以单继承,也可以多继承。
C:设计理念区别
抽象类被继承体现的是:”is a”的关系。抽象类定义的是共性功能。
接口被实现体现的是:”like a”的关系。接口定义的是扩展功能。
如果给上面的例子加一个接口用来实现老师和学生中抽烟的功能,相应代码应该如何实现:

//接口public interface Inter {    public abstract void smoke();}//抽烟老师继承老师public class SmokeTeacher extends Teacher implements Inter{    @Override    public void smoke() {        System.out.println("有的老师也会抽烟");    }    public SmokeTeacher(){}    public SmokeTeacher(String name,int age){        setName(name);        setAge(age);    }}//抽烟学生继承学生public class SmokeStudent extends Student implements Inter{    @Override    public void smoke() {        System.out.println("有的学生也抽烟");    }    public SmokeStudent(){}    public SmokeStudent(String name,int age){        setName(name);        setAge(age);    }}//重新写一个测试类public class Test {    public static void main(String[] args) {        Adult t=new Teacher();        t.setName("方大同");        t.setAge(33);        t.work();        SmokeTeacher st=new SmokeTeacher("方大同",33);        System.out.println(st.getName()+" "+st.getAge());        st.smoke();        Adult s=new Student("薛之谦",32);        System.out.println(s.getName()+" "+s.getAge());        SmokeStudent ss=new SmokeStudent();        ss.work();        ss.smoke();     }}

编译运行的结果如下:
老师的工作是教书育人
方大同 33
有的老师也会抽烟
薛之谦 32
学生的天职是学习
有的学生也抽烟

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩天天玩游戏怎么办 手机分期人死了怎么办 人死了手机欠费怎么办 晚上想玩手机怎么办 孩子溺水后发烧怎么办 去台湾多次签证怎么办 怀孕不能玩手机怎么办 孕期天天玩手机怎么办 小孩子在家偷钱怎么办 小朋友被鸡抓伤怎么办 宝宝在学校不说怎么办? 宝宝不和小朋友玩怎么办 初中孩子不想上学怎么办 孩子装病不想上学怎么办 中学生叛逆不愿意上学怎么办 孩子去幼儿园哭闹怎么办 孩子哭闹不上学怎么办 孩子中班还哭怎么办 小孩子不爱上幼儿园怎么办 小孩子不爱去幼儿园怎么办 宝宝去幼儿园哭闹怎么办 宝宝上幼儿园哭闹怎么办 小朋友上幼儿园哭闹怎么办 迷路了怎么办幼儿故事 大班迷路了怎么办故事 玩手机眼睛干涩怎么办 宝睡觉不踏实怎么办 觉得自己老了怎么办 微信没自动扣费怎么办 东西放在家找不到怎么办 刚怀孕同房流产怎么办 开车遇上送葬的怎么办 流水钓鱼走漂怎么办 水库里小鱼太多怎么办 英国留学生怎么办澳签 老赖欠货款不还怎么办 老赖失信出国怎么办 打完预防针呕吐怎么办 媳妇老说离婚怎么办 老公吵架要出走怎么办 惹老婆生气了怎么办