【Java学习4】面向对象之继承和多态

继承

继承主要解决代码重用问题,利用继承可以从已有的类继续继承派生出新的子类,也可以利用子类扩展出更多的操作功能。

继承的实现

/*
class 子类 extends 父类{}
子类又称为派生类
父类又称为超类
*/
class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    /*getter省略 */
    public Person(){}
    public Person(String name){
        this();
        this.name = name;
    }
    public Person(String name, int age){
        this(name);
        this.age = age;
    }
    public String getInfo(){
        return "name:" + this.name + "\t age:" + this.age;
    }
}
class Student extends Person{
    private String school;  
    public void setSchool(String school){
        this.school = school;
    }
}
public class Text{
    public static void main(String args[]){
        Student stu = new Student();
        stu.setName("小明"); //子类可以使用父类的方法
        stu.setAge(20);
        stu.setSchool("清华");  //子类也可以扩展自己的功能
        System.out.print(stu.getInfo());
    }
}

继承的限制

  • java不允许多重继承,但是允许多层继承
//多层继承
class A{}
class B extends A{}
class C extends B{}
  • 子类在继承父类时,会继承父类中的全部操作,但是对于所有的私有操作属于隐式继承,而所有的非私有操作属于显式继承
  • 在子类对象构造前,一定会默认调用父类的构造,以保障父类对象先实例化,子类对象后实例化

super关键字

super()可以调用在子类构造方法中调用父类的构造方法

class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    /*getter省略 */
    public Person(){}
    public Person(String name){
        this();
        this.name = name;
    }
    public Person(String name, int age){
        this(name);
        this.age = age;
    }
    public String getInfo(){
        return "name:" + this.name + "\t age:" + this.age;
    }
}
class Student extends Person{
    private String school;
    public Student(String name,int age){
        super(name,age);//使用super调用父类的构造方法
    }
    public void setSchool(String school){
        this.school = school;
    }
}
public class Text{
    public static void main(String args[]){
        Student stu = new Student("小明",22);
        System.out.print(stu.getInfo());
    }
}

super().父类方法(),可以在子类中调用父类的方法。

class A{
	public void print(){
	System.out.print("父类方法");
	}
}
class B extends A{
	public void print(){
	super().print();//调用父类的方法
	System.out.print("父类方法");
	}
}

覆写

如果子类定义的方法和属性,在父类中出现同名时,这样的操作就叫做覆写。

class A{
	public void fun(){
		System.out.print("A类的fun方法");
	}
}
class B extends A{
	public void fun(){
		System.out.print("B类中的fun方法");
	}
}
//那么当B类定义了一个和A类完全一样的fun方法时,实例化B类对象,调用fun方法则是B类覆写过的方法。

覆写原则:如果子类覆写了方法,并且实例化子类对象,那么调用的一定是被覆写的方法。

覆写限制:被之类覆写的方法不能拥有比父类更严格的访问控制权限。public > default > private

属性的覆写在实际开发中没有意义,因为类中的属性都是private封装,那么一旦封装后属性覆写没有意义,父类定义的私有属性子类根本看不见,更不会互相影响。

this和super的区别

  • this调用本类构造方法、本类方法、本类属性。
  • super调用父类构造方法、父类方法、父类属性

final关键字

final称之为终结器,可以使用final定义类、方法和属性。

  • 使用final定义的类不能再有子类,即任何类不能继承以final声明的父类。一般情况下不使用final定义类。
  • 使用final定义的方法不能被子类所覆写
  • 使用final定义的变量就称为了常量,不能修改。
final int i = 10;
i = 100;//错误,不能修改常量
//全局常量:
public static final String MSG = "heloo";

多态

多态性在开发中有两个方法:

  • 方法的多态性:重载和覆写
    重载:同一个方法名称,根据不同参数类型即个数可以完成不同功能。
    覆写:同一个方法,根据实例化的子类对象不同,所完成的功能不同
  • 对象的多态性:父子类对象的转换
    向上转型:子类对象变成父类对象:父类 父类对象 = 子类实例,自动转换
    向下转型:父类对象变成子类对象:子类 父类对象 = (子类) 父类实例

向上转型:子类对象变成父类对象

class A{
	public void print(){
		System.out.print("父类print方法");
	}
}
class B extends A{
	public void print(){
		System.out.print("子类print方法");
	}
}
A a = new B();//向上转型,子类对象变成父类对象
a.print();//调用的是子类覆写过的方法

向下转型:父类对象变成子类对象

class A{
	public void print(){
		System.out.print("父类print方法");
	}
}
class B extends A{
	public void print(){
		System.out.print("子类print方法");
	}
}
A a = new B();
B b = (B) a;//向下转型,父类对象变成子类对象
b.print();//调用的是子类覆写过的方法
//向下转型是有前提条件的:必须发生向上转型后才可以向下转型。
//如果是两个没有关系的对象发送强制转换,则会异常。

抽象类

利用抽象类可以明确地定义子类需要覆写地方法,这样代码开发也就更加标准。

抽象类定义

抽象方法使用abstract关键字定义,拥有抽象方法的类一定属于抽象类。

abstract class A{ //定义抽象类
	public void fun(){
		//普通方法
	}
	//没有方法体,并且存在abstract关键字表示抽象方法
	public abstract void print();
}
class B extends A{
	public void print(){
		//子类必须强制要求覆写此方法
	}
}

接口

利用抽象类可以实现子类覆写方法的控制,但是抽象类有很大一个问题:单继承限制。所以为了打破这个限制,需要使用Java接口来解决。

接口的定义

使用interface关键字进行接口的定义

interface A{
	public static final String MSG = "ttt";//全局常量
	public abstract void print();//抽象方法
}

接口使用原则:

  • 接口必须有子类,但是此时子类可以使用implements关键字实现多个接口,避免单继承限制。
  • 接口的子类必须要覆写接口中的全部抽象方法
  • 接口的对象可以利用子类对象的向上转型进行实例化操作
interface A{
	public abstract void print();
}
interface B{
	public abstract void get();
}
class X implements A,b{ //X类实现A、B接口
	public void print(){
		//覆写A接口的抽象方法
	}
	public void get(){
		//覆写B接口的抽象方法
	]
}
X x = new X(); //实例化子类
A a = x; //向上转型
B b = x; //向上转型
a.print(); //调用被覆写过的方法

猜你喜欢

转载自blog.csdn.net/a15803617402/article/details/85273388