您的位置:首页 > 编程语言 > Java开发

JAVA-6-继承、super、final、多态、抽象类、接口

2017-04-10 22:32 501 查看
一:继承

  1.1如何表达这个关系呢?

    通过extends关键字可以实现类与类的继承

      格式:

        class 子类名 extends 父类名 {

        …

        }

      父类也可以叫做基类,超类;子类也可以叫做派生类

  举例对比继承和非继承下代码,需求:

    学生类:

      成员变量:name,age

      构造方法:无参,带参

      成员方法:getXxx()/setXxx(),eat(),sleep()

    老师类:

    成员变量:name,age

      构造方法:无参,带参

      成员方法:getXxx()/setXxx(),eat(),sleep()      

非继承版代码如下:

学生类代码:

package exercise01;

public class Student {
//  私有化成员变量
private String name ;
private int age ;
//  为被私有化的成员变量分别提供setXxx/getXxx对外公共访问方法
public void setName(String name){
this.name=name;//this指代本类中对象,谁调用我我指代谁
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}

//  提供无参、有参构造方法
public Student(){}
public Student(String name,int age){
this.age=age;
this.name=name;
}

//  提供其他成员方法
public void eat(){
System.out.println("学生爱吃米饭");
}
public void sleep(){
System.out.println("学生喜欢侧着睡");
}
}


老师类代码:

package exercise01;

public class Teacher {
private String name;
private int age;

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 Teacher(){}
public Teacher(String name,int age){
this.age=age;
this.name=name;
}

public void eat(){
System.out.println("老师爱吃馒头");
}
public void sleep(){
System.out.println("老师喜欢躺着睡");
}

}


测试类:

package exercise02;

public class Test {
public static void main(String[] args) {
Student s = new Student();//新建学生类对象
//      利用set方法进行初始化
s.setAge(10);
s.setName("lisi");
s.eat();
s.sleep();
System.out.println(s.getName()+"  "+s.getAge());
System.out.println("-----");
Teacher t=new Teacher();
t.sleep();
}

}
//学生爱吃米饭
//人类需要睡眠
//lisi  10
//-----
//老师喜欢倒着睡
//学生爱吃米饭
//学生喜欢侧着睡
//张三   23
//------
//12  李四
//老师爱吃馒头
//老师喜欢躺着睡


1.2需求:(需要加入方法重写)

  针对老师类、学生类按照我们刚才对继承的概述,我们可以找一个父类。

    人类:

      成员变量:name,age

      构造方法:无参,带参

      成员方法:getXxx()/setXxx(),eat(),sleep()

那么,学生类继承人类就可以了;老师类同样继承人类就可以了。

继承版代码如下:

①建立Person类:

package exercise02;

//建立Person类
public class Person {
//  私有化成员变量
private String name;
private int age;
//  分别为私有化成员变量提供set/get对外公共访问方式
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 Person(){}
public Person(String name ,int age){
this.age=age;
this.name=name;
}
//  提供其他成员方法
public void eat(){
System.out.println("人类需要吃饭");
}
public void sleep(){
System.out.println("人类需要睡眠");
}
}


②学生类继承Person类,并重写eat()方法:

package exercise02;

public class Student extends Person{//学生类继承Person类
//  如果父类的方法不满足子类的需求,子类可以写一个一摸一样的方法在自己的类体中,这样就实现了方法重写
//  由于Person类中的eat()方法不能满足学生类eat()方法,因此需要重写eat()方法
public void eat(){
System.out.println("学生爱吃米饭");
}
}


③老师类继承Person类,并重写sleep()方法:

package exercise02;

public class Teacher {
//重写sleep()方法
public void sleep(){
System.out.println("老师喜欢倒着睡");
}
}


④新建Test类进行测试:

package exercise02;

public class Test {
public static void main(String[] args) {
Student s = new Student();//新建学生类对象
//      利用set方法进行初始化
s.setAge(10);
s.setName("lisi");
s.eat();
s.sleep();
System.out.println(s.getName()+"  "+s.getAge());
System.out.println("-----");
Teacher t=new Teacher();
t.sleep();
}
}
//学生爱吃米饭
//人类需要睡眠
//lisi  10
//-----
//老师喜欢倒着睡


  继承的好处:

    A:提高了代码的复用性,多个类相同的成员可以放到同一个类中

    B:提高了代码的维护性,如果功能的代码需要修改,修改一处即可

    C:让类与类之间产生了关系,是多态的前提

  方法重写(子类的方法名,参数和父类完全一样,将父类方法覆盖):

    1.必须存在继承关系

    2.父类的方法满足不了你的需求,此时你就需要重写父类的方法,实现自己想要实现的功能

1.3继承的特点:

  A:Java只支持单继承,不支持多继承。

  B:Java支持多层(重)继承(继承体系)。

package com.edu_03;
class GrandFather{}
class Father extends GrandFather{}//java不支持多继承,但支持多重继承
class Mother{}
//创建一个儿子类
//class Son extends Father,Mother{}//错误,java中只支持单继承
class Son extends Father{}
public class ExtendsDemo {
}


那么什么时候使用继承呢?

  继承中类之间体现的是:”is a”的关系。

  采用假设法。

    举例:水果,香蕉(香蕉是一个水果,继承)

    举例:水杯,水果 (水果是一个水杯???不能采用继承。)

    举例:动物,狗 (狗是一个动物,继承)

1.4类的组成:成员变量、构造方法、成员方法

  继承间的成员变量关系:

    A:名字不同,非常简单,直接用

    B:名字相同

      首先在子类局部范围找

      然后在子类成员范围找

      最后在父类成员范围找(肯定不能访问到父类局部范围)

      如果还是没有就报错。(不考虑父亲的父亲…)

      就近原则。

1.5怎么去访问父亲的成员呢?java就提供了一个关键字:super

  super:super代表父类存储空间的标识(可以理解为父类对象)

    this和super的使用区别?

      A:成员变量

        this.成员变量 本类的成员变量

        super.成员变量 父类的成员变量

      B:成员方法

        this.成员方法() 本类的成员方法

        super.成员方法()父类的成员方法

        

1.6继承间构造方法的关系:

  子类中所有的构造方法默认都会访问父类中空参数的构造方法(super())

  ①为什么呢?

    因为子类会继承父类中的数据,可能还会使用父类的数据。

    所以,子类初始化之前,一定要先完成父类数据的初始化。

    每个子类的构造方法的第一行,有一条默认的语句super();

    注意:仅仅是完成数据的初始化,创建对象目前必须用new申请空间。

  ②假如父类没有无参构造方法,该怎么办呢?

    A:调用父类的其他构造方法。带参构造。

      怎么访问呢?

        super(…)

    注意:super(…)或者this(….)必须出现在第一条语句上。因为如果可以放后面的话,就会对父类的数据进程多次初始化。所以,只能放在第一条语句上。

    建议:永远给出无参构造方法。

    

需求:请在show方法中输出40,30,20,10,50

package com.edu_03;

class Fu {
public int num = 10;
public int num4 = 50;
}

class Zi extends Fu {
public int num2 = 20;
public int num = 30;

public void show() {
int num = 40;
System.out.println(num);//输出40,就近原则
System.out.println(this.num);//this代表的是本类的一个对象,谁调用我,我指代谁
System.out.println(num2);
System.out.println(super.num);//super可以理解为父类的一个对象
System.out.println(num4);
}
}

public class ExtendsDemo2 {
public static void main(String[] args) {
//创建Zi类的对象
Zi z = new Zi();
z.show();
}
}


1.6猫狗案例继承版

  猫:

    成员变量:type,name,age

    构造方法:无参,带参

    成员方法:getXxx()/setXxx(),show()

  狗:

    成员变量:type,name,age

    构造方法:无参,带参

    成员方法:getXxx()/setXxx(),show()

    

  提取出动物类,完成代码,并测试。

①动物类

package com.edu_05;

public class Animal {
private String type;
private int age;
private String name;

public Animal(){}
public Animal(String name,String type,int age){
this.name = name;
this.type = type;
this.age = age;
}

public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}

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 void eat(){
System.out.println("动物喜欢吃粮食");
}
}


②狗类

package com.edu_05;

public class Dog extends Animal{
//有参数和无参数的构造方法
public Dog(){}
public Dog(String name,String type,int age){
setAge(age);
setName(name);
setType(type);
}

//狗喜欢吃肉
public void eat(){
System.out.println("狗喜欢吃肉");
}
}


③猫类

package com.edu_05;

public class Cat extends Animal{
public Cat(){}
public Cat(String name,String type,int age){
setAge(age);
setName(name);
setType(type);
}

//猫喜欢吃鱼
public void eat(){
System.out.println("猫咪喜欢吃鱼");
}
}


④测试:

package com.edu_05;

public class Test {
public static void main(String[] args) {
//创建对象
Dog d = new Dog();
d.eat();

System.out.println("------------");
Cat c = new Cat("bob", "波斯猫", 2);
c.eat();
System.out.println(c.getAge()+"  "+c.getName()+"  "+c.getType());

}
}
//狗喜欢吃肉
//------------
//猫咪喜欢吃鱼
//2  bob  波斯猫


1.7 水果案例继承版

  苹果:

    成员变量:品种,颜色

    构造方法:有参无参

    成员方法:getXxx()/setXxx();show()

  橘子:

    成员变量:品种,颜色

    构造方法:有参无参

    成员方法:getXxx()/setXxx();show()

  提取水果类,完成代码,并测试

①水果类:

package com.edu_06;

public class Fruit {
//私有化成员变量
private String type;
private String color;
//提供无参有参构造方法
public Fruit(){}
public Fruit(String type,String color){
this.type=type;
this.color=color;
}
//为私有化成员变量提供给set/get方法
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 show(){
System.out.println(type+"  "+color+"  ");
}
}


②苹果类

package com.edu_06;

public class Apple extends Fruit{
//有参和无参构造
public Apple(){}
public Apple(String type,String color){
setColor(color);
setType(type);
}

public void show(){
System.out.println("苹果很好吃");
}
}


③橘子类

package com.edu_06;

public class Orange extends Fruit{
//有参和无参构造
public Orange(){}
public Orange(String type,String color){
setColor(color);
setType(type);
}

public void show(){
System.out.println("橘子好吃又营养");
}
}


④测试

package com.edu_06;

public class Test {
public static void main(String[] args) {
//创建Apple对象
Apple a = new Apple();
a.show();
a.setColor("红色");
a.setType("红富士");
System.out.println(a.getColor()+"  "+a.getType());
Orange ora = new Orange("柑橘","黄色");
ora.show();
System.out.println(ora.getColor()+"  "+ora.getType());
}
}
//苹果很好吃
//红色  红富士
//橘子好吃又营养
//黄色  柑橘


二:final关键字

  在实际开发的时候,有些方法的内容一旦写定后,就不允许被改动。即时是子类,也不允许。那么该怎么解决这个问题呢?java为了解决这样的问题就提供了一个关键字:final,最终的意思。它可以修饰类,方法,变量。

  final特点:

    修饰方法,方法不能被重写。

    修饰类,类不能被继承。

    修饰变量,变量的值不能再改动。其实这个时候变量已经变成了常量。

  常量:

    A:字面值常量

      ‘a’,12,”hello”

    B:自定义常量

      就是把变量用final修饰。

  定义一个常量:

     final 数据类型 变量名;

三:多态

3.1多态:同一个对象,在不同时刻表现出来的不同状态。

  举例:

    A:猫

      猫是猫

      猫是动物

    B:水

      水(液态)

      冰(固态)

      水蒸气(气态)

多态的前提:

  A:有继承关系

  B:有方法重写(不是必要条件,但是只有有了方法重写多态才有意义)

  C:有父类引用指向子类对象

    Fu f = new Fu();

    左边:Fu类型的引用  右边:Fu类型的对象

    Zi z = new Zi();

    Fu f = new Zi();

3.2成员访问特点

  A:成员变量  编译看左边,运行看左边

  B:构造方法  子类构造默认访问父类的无参构造

  C:成员方法(重点理解)  编译看左边,运行看右边。为什么变量和方法不一样呢?因为方法存在方法重写。

  D:静态成员方法  编译看左边,运行看左边。因为静态的内容是和类相关的,与对象无关。

3.3练习:(猫狗案例演示)

  如何使用子类特有功能?

    A:创建子类对象

    B:把父类引用转为子类对象

      ①向上转型

        从子到父

        父类引用指向子类对象

      ②向下转型

        从父到子

        父类引用转为子类对象

①动物类:

package com.edu_09;

public class Animal {
private String type;
private int age;
private String name;

public Animal(){}
public Animal(String name,String type,int age){
this.name = name;
this.type = type;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age  = age;
}
public int getAage(){
return age;
}
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}

//吃的方法
public void eat(){
System.out.println("动物喜欢吃饭");
}
}


②猫类:

package com.edu_09;
public class Cat extends Animal{
public Cat(){}
public Cat(String name,String type,int age){
setAge(age);
setName(name);
setType(type);
}

//猫喜欢池鱼
public void eat(){
System.out.println("猫喜欢吃鱼");
}

//猫有一个特有的功能,猫会捉老鼠
public void catchMouce(){
System.out.println("猫有一个捉老鼠的特有技能");
}
}


③狗类:

package com.edu_09;
public class Dog extends Animal{
public Dog(){}
public Dog(String name,int age,String type){
setAge(age);
setName(name);
setType(type);
}

//狗有一个特有技能会看门
public void lookDoor(){
System.out.println("狗会看门");
}
}


④测试:

package com.edu_09;
public class Test {
public static void main(String[] args) {
//使用多态的方式创建一个Cat对象
Animal a = new Cat();
a.eat();
//a.catchMouce();编译不通过,因为多态调用时编译看父类,父类中没有catchMouce()便会报错。
//需求:在这里调用猫中特有功能,捉老鼠
//方式1:创建Cat对象,使用Cat类型去接受
Cat c = new Cat();
c.catchMouce();
System.out.println("------------");

//方式2:向下转型,将父类引用转换成子类对象
Cat c2 = (Cat)a;
c2.catchMouce();

System.out.println("--------------");
//将a这个引用转换成Dog对象???
//Dog d = (Dog)a;编译通过,运行出错。java.lang.ClassCastException:类型转换异常
//d.eat();
//d.lookDoor();

System.out.println("----------------");
Animal a2 = new Dog();
a2.eat();
Dog d = (Dog)a2;
d.lookDoor();
}
}
//猫喜欢吃鱼
//猫有一个捉老鼠的特有技能
//------------
//猫有一个捉老鼠的特有技能
//--------------
//----------------
//动物喜欢吃饭
//狗会看门


四:抽象类

4.1抽象类特点:

  A:抽象类和抽象方法必须用abstract关键字修饰

  B:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类

  C:抽象类不能实例化

  那么,如果实例化并使用呢?按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。

  D:抽象类的子类,要么是抽象类,要么重写抽象类中的所有抽象方法

4.2抽象类的作用:强制要求子类必须要重写某些方法。

4.3抽象类 – 特点 – 成员特点 – 案例

  类的组成:成员变量,构造方法,成员方法

  抽象类的成员:

    成员变量:可以是变量,也可以是常量。

    构造方法:有构造方法

      不能实例化,构造方法有什么用呢? 用于子类访问父类数据的初始化。

    成员方法:既可以是抽象的,也可以是非抽象的。

4.3 抽象类练习

  以后我们在写代码的时候,有这样的分析过程。

    分析:从具体到抽象。

    实现:从抽象到具体。

    使用:使用具体的类。

  例如,猫:

       成员变量:name,age,type

       构造方法:有参无参

       成员方法:getXxx()/setXxx();eat(),catchMouse()

     狗:

       成员变量:name,age,type

       构造方法:有参无参

       成员方法:getXxx()/setXxx();eat(),lookDoor()

  发现有共性的内容,所以我们就提取出一个父类出来:

    动物:抽象类

       成员变量:name,age,type

       构造方法:有参无参

       成员方法:getXxx()/setXxx()

            eat()—抽象的

    猫继承自动物,狗:继承自动物

①动物类:

package com.edu_11;
public abstract class Animal {
private String type;
private String name;

public Animal(){}
public Animal(String type,String name){
this.name = name;
this.type = type;
}

public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}

//吃饭的抽象方法
public abstract void eat();
}


②猫类:

package com.edu_11;
public class Cat extends Animal{
public Cat(){}
public Cat(String name,String type){
setName(name);
setType(type);
}

@Override
public void eat() {
System.out.println("猫爱吃鱼");
}

//猫会捉老鼠
public void catchMouse(){
System.out.println("猫会逮老鼠");
}
}


③狗类:

package com.edu_11;
public class Dog extends Animal{
public Dog(){}
public Dog(String name,String type){
setName(name);
setType(type);
}

@Override
public void eat() {
System.out.println("狗爱吃肉");
}

//狗特有的看门方法
public void lookDoor(){
System.out.println("狗会看门");
}
}


④测试:

package com.edu_11;
public class Test {
public static void main(String[] args) {
//利用多态的方式创建一个狗的对象
Animal a = new Dog();
a.eat();
Dog d = (Dog)a;
d.lookDoor();
System.out.println("--------------");
//使用猫的有参构造创建一个对象
Animal a2 = new Cat("bob", "加菲猫");
a2.eat();
System.out.println(a2.getName()+"  "+a2.getType());
Cat c=(Cat)a2;
c.catchMouse();
}
}
//狗爱吃肉
//狗会看门
//--------------
//猫爱吃鱼
//bob  加菲猫
//猫会逮老鼠


五:接口

5.1 认识接口:不是我们现实生活中的usb接口等等实物的接口,类实现接口代表着这个类自身功能的一种扩展,所以接口代表着一种扩展的能力。

5.2接口的特点:

  A:定义接口要用关键字interface表示

    格式:interface 接口名 {}

  B:类实现接口用implements表示

    格式:class 类名 implements 接口名 {}

  C:接口不能实例化

    那么,接口如何实例化呢?按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。

  D:接口的实现类

    要么是抽象类,要么重写接口中的所有抽象方法

    

      多态的前提:

        A:有继承或者实现关系

        B:有方法重写

        C:有父类引用或者父接口引用指向子类或者实现类对象

      多态分类:

        A:具体类多态

        B:抽象类多态

        C:接口多态

5.3接口的成员特点:

  A:成员变量

    只能是常量。默认修饰符:public static final

  B:构造方法

    没有构造方法

  C:成员方法

    只能是抽象方法。默认修饰符:public abstract

5.4

  类与类:

    继承关系。只能单继承,可以多层(重)继承。

  类与接口:

    实现关系。可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口。

  接口与接口:继承关系。可以单继承,也可以多继承。

  

5.5接口和抽象类的关系最后分析:

  抽象类和接口的区别

    A:成员区别

      抽象类:

        成员变量:可以是变量,也可以是常量

        构造方法:有构造方法

        成员方法:可以是抽象方法,也可以是非抽象方法

      接口:

        成员变量:只能是常量。默认修饰符 public static final

        成员方法:只能是抽象方法。默认修饰符 public abstract

    B:关系区别

      类与类:

        继承关系。只能单继承,可以多层(重)继承。

      类与接口:

        实现关系。可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口。

      接口与接口:继承关系。可以单继承,也可以多继承。

    C:设计理念区别

      抽象类被继承体现的是:”is a”的关系。抽象类定义的是共性功能。

      接口被实现体现的是:”like a”的关系。接口定义的是扩展功能。

5.6继承,抽象类,接口代码综合演练。猫狗案例,加入跳高的额外功能

  猫:

    成员变量:name,age

    构造方法:无参,带参

    成员方法:getXxx()/setXxx()

         show()

         catchMouse()

         eat()

  跳高猫:继承自猫

    成员方法:跳高

  狗:

    成员变量:name,age

    构造方法:无参,带参

    成员方法:getXxx()/setXxx()

         show()

         lookDoor()

         eat()

  跳高狗:继承自狗

    成员方法:跳高

无论猫还是狗,都是动物,所以我们提取出一个动物类:

  跳高接口:跳高

  动物类:抽象类

    成员变量:name,age

    构造方法:无参,带参

    成员方法:getXxx()/setXxx()

         show(){}

         eat(); 抽象方法

  猫:继承自动物

    构造方法:无参,带参

    成员方法:catchMouse()

         eat()

  跳高猫:继承自猫,实现跳高接口

    构造方法:无参,带参

    成员方法:跳高

  狗:继承自动物

    构造方法:无参,带参

    成员方法:lookDoor()

      eat()

 跳高狗:继承自狗,实现跳高接口

   构造方法:无参,带参

   成员方法:跳高

代码如下:

①动物类

package com.edu_13;
public abstract class Animal {
//私有化成员变量
private String name;
private int age;

//有参无参构造
public Animal(){}
public Animal(String name,int age){
this.name = name;
this.age = age;
}

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 eat();
}


②猫类

package com.edu_13;
public class Cat extends Animal{

public Cat(){}
public Cat(String name,int age){
setAge(age);
setName(name);
}

@Override
public void eat() {
System.out.println("猫爱吃鱼");
}

//所有的猫都会逮老鼠
public void catchMouse(){
System.out.println("猫会逮老鼠");
}
}


③狗类

package com.edu_13;
public class Dog extends Animal{
//有参无参构造
public Dog(){}
public Dog(String name,int age){
setAge(age);
setName(name);
}

@Override
public void eat() {
System.out.println("狗吃骨头");
}

//所有的狗都会看门
public void lookDoor(){
System.out.println("狗会看家");
}
}


④接口

package com.edu_13;
public interface Inter {
public abstract void jump();
}


⑤跳高猫

package com.edu_13;
public class JumpCat extends Cat implements Inter{

public JumpCat(){}
public JumpCat(String name,int age){
setAge(age);
setName(name);
}

@Override
public void jump() {
System.out.println("经过多年的刻苦训练,终于练成了跳高技能");
}
}


⑥跳高狗

package com.edu_13;
public class JumpDog extends Dog implements Inter{

public JumpDog(){}
public JumpDog(String name,int age){
setAge(age);
setName(name);
}

@Override
public void jump() {
System.out.println("这条狗不简单呐,居然会跳高");
}
}


⑦测试

package com.edu_13;
public class Test {
public static void main(String[] args) {
//多态的方式创建一个普通狗
Animal a = new Dog();
a.eat();
Dog d = (Dog)a;
d.lookDoor();
System.out.println("------------------");
//创建一个跳高狗
JumpDog jd = new JumpDog();
jd.eat();
jd.lookDoor();
jd.jump();
System.out.println("------------------");

Animal b = new Cat();
b.eat();
Cat c = (Cat)b;
c.catchMouse();
System.out.println("------------------");
//创建一个跳高狗
JumpCat jc = new JumpCat();
jc.eat();
jc.catchMouse();
jc.jump();
}
}
//狗吃骨头
//狗会看家
//------------------
//狗吃骨头
//狗会看家
//这条狗不简单呐,居然会跳高
//------------------
//猫爱吃鱼
//猫会逮老鼠
//------------------
//猫爱吃鱼
//猫会逮老鼠
//经过多年的刻苦训练,终于练成了跳高技能
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐