面向对象——继承、多态、抽象类、接口

一、继承

1、继承:类和类之间满足一个类属于(is a)另一个类

例如:dog is an animal

2、继承关键字:extends                             dog extends animal;

其中,dog称为子类或派生类,animal称为父类或者基类

3、继承规则

(1)使用继承必须满足 is a 关系

(2)一个子类只能使用extends继承一个父类(单继承),继承允许多层继承,但不允许多重继承。

例如:Labrador extends dog; dog extends animal; 拉布拉多犬是狗的子类,狗是动物的子类,拉布拉多犬不能同时继承狗和动物两个父类。 

(3)子类会继承父类的所有属性和方法

① 显式继承(public属性和方法),可以直接使用

② 隐式继承(private属性和方法),子类继承了,但无法直接调用,必须通过父类提供的方法来操做

public class Animal {
    public String name;
    private int age;
    public int getAge(int age){       //age是私有属性,需要提供getter方法才能使用
        return age;
    }
    public void eat(String food){
        System.out.println(this.name +"正在吃" +food);
    }
}
public class Dog extends Animal{
}
public class Test {
    public static void main(String[] args) {
        Dog dog=new Dog();
        dog.name="小狗";
        System.out.println(dog.name+"今年"+dog.getAge(2)+"岁了");
        dog.eat("meat");
    }
}

 

注:静态的成员和方法是归于某个类所有,和普通方法继承使用的区别在于通过子类对象访问还是类名称访问。

4、protected访问权限

private < default < protected < public.

protected只在当前类和子类的内部可见,出了这些类就不可用了。包可见的范围,protected一定可见。  protected权限在同包中没有继承关系的类之间是可见的,在不同包的有继承关系的子类之间是可见的。

5、super关键字

(1)修饰属性,表示直接从父类中寻找同名属性,若直接父类中没有同名属性,则继续向上(直接父类的父类)找。

public class Animal {
    public String name="动物";
    private int age;
    public int getAge(int age){
        return age;
    }
    public void eat(String food){
        System.out.println(this.name +"正在吃" +food);
    }
}
public class Dog extends Animal{
}
public class Labrador extends Dog{
    public static void main(String[] args) {
        Labrador labrador=new Labrador();
        labrador.fun();
    }
    public void fun(){
        System.out.println(super.name);
    }
}

 Labrador的父类Dog中没有name这个属性,就继续向上找,在Dog的父类animal中找到了name属性,最后的输出为animal中的name。

 (2)修饰方法,表示从父类中寻找方法(①构造方法 ②普通方法)

产生子类对象之前,默认调用父类的构造方法产生父类对象,若父类还有继承,则先产生祖类,然后才会执行子类的构造方法。

public class Animal {
    public String name;
    private int age;
    public Animal(){
        System.out.println("Animal的无参构造");
    }
}
public class Dog extends Animal{
    public Dog(){
        System.out.println("Dog的无参构造");
    }
}
public class Labrador extends Dog{
    public static void main(String[] args) {
        Labrador labrador=new Labrador();
    }
    public Labrador(){
        System.out.println("Labrador的无参构造");
    }
}

 ① super修饰构造方法

super(父类构造方法的参数);

super( );直接父类的无参构造,可写可不写。

若父类中不存在无参构造,则子类构造方法的首行必须显式使用父类的有参构造super(有参构造)

public class Animal {
    public String name;
    private int age;
    public Animal(String name){
        this.name=name;
        System.out.println("2、Animal的有参构造");
    }
}
public class Dog extends Animal{
    public Dog(){
        super("胖胖");
        System.out.println("Dog的无参构造");
    }
    public static void main(String[] args) {
        Dog dog=new Dog();
    }
}

产生一个dog对象,dog的父类animal中没有无参构造,则产生dog对象时,必须显式的调用父类的有参构造。

注:super( )和this( )不能同时显式出现。 

public class Animal {
    public String name;
    private int age;
    public Animal(){
        System.out.println("Animal的无参构造");
    }
}
public class Dog extends Animal{
    public Dog(){
        System.out.println("Dog的无参构造");
    }
    public Dog(String name){
        //super();    实际上子类构造方法的首行已经默认使用了父类的无参构造
        this();
        System.out.println("Dog的有参构造");
    }
    public static void main(String[] args) {
        Dog dog=new Dog("麻蛋");
    }
}

 

 ② super修饰普通方法

super修饰普通方法时,从直接父类中寻找,super不能直接指代当前父类对象的引用。

public class Animal {
    public String name;
    private int age;
    public Animal(){
        System.out.println("Animal的无参构造");
    }
    public Animal(String name){
        this.name=name;
    }
    public void eat(){
        System.out.println(this.name+"正在吃"+"food");
    }
}
public class Dog extends Animal{
    public Dog(){
        System.out.println("Dog的无参构造");
    }
    public Dog(String name){
        super.eat();
        System.out.println("Dog的有参构造");
    }

    public static void main(String[] args) {
        Dog dog=new Dog("胖胖");
    }
}

 此时,dog子类调用了父类的eat方法。因为dog类中并没有覆写父类的eat方法,所以没有输出“胖胖正在吃food”,而是父类中的默认名字null正在吃food。

6、final关键字

final修饰属性该属性不可以修改,是个常量
final修饰类表示这个类不能被继承
final修饰方法该方法不能被覆写

7、组合关系

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。

例如,学校这个类是由学生、老师等组成的。

public class School {
    Student student;
    Teacher teacher;
}
class Student{
    String sex;
}
class Teacher{
    int age;
    public Teacher(int age){
        this.age=age;
    }
}

 二、多态

多态:是指同一个引用(变量名称)调用同一个方法名,根据引用指向不同的对象可以表现出不同的行为。

最主要的多态:继承 + 方法重写

1、向上转型:可以实现参数统一化

父类名称 父类引用 = new  子类实例

Animal animal = new Dog();

类名称 类引用 = new 该类对象();

Dog dog = new Dog();

创建的两个对象都是Dog,一个是通过父类创建的,一个是通过自身类创建的。

public class Animal {
    public String name;
    private int age;
    public Animal(){
    }
    public Animal(String name){
        this.name=name;
    }
}
public class Dog extends Animal{
    public Dog(){
    }
    public Dog(String name){
       super.name=name;
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal=new Dog();
        animal.name="大胖子";
        Dog dog=new Dog();
        dog.name="小胖子";
        System.out.println(animal.name);
        System.out.println(dog.name);
    }
}

 

方法重写(override):发生在有继承关系的类之间,子类定义了和父类除了权限不同,其他全都相同的方法(返回值类型相同,或者至少是向上转型),这样的一组方法称为方法重写。子类权限大于等于父类权限,才可以进行重写(private权限的方法不能被重写)。重写方法不能在static方法中,只发生在普通方法中。

若子类重写了该方法,则调用的是重写后的方法;若子类没有进行方法重写,则向上搜索,找父类的该方法进行调用,若父类也没有该方法,则继续向上搜索,找祖类,调用祖类的方法。 

2、向下转型:将父类引用强制转换为子类引用

已知只有只有一个父类引用,要使用子类拓展的方法,此时需要把父类引用还原为子类引用。要发生向下转型必须先发生向上转型。

子类名称 子类引用 = (子类名称) 父类引用;

public class Animal {
    public String name;
    private int age;
    public Animal(){
    }
    public Animal(String name){
        this.name=name;
    }
}
public class Dog extends Animal{
    public Dog(){
    }
    public Dog(String name){
       super.name=name;
    }
    public void swim(){
        System.out.println(name+"在游泳");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal=new Dog("猫咪");
        Dog dog=(Dog) animal;
        dog.swim();
    }
}

创建了一个dog对象,引用类型为animal(父类);此时只能调用父类的方法,若想要调用子类的方法,必须将父类引用强制转换为子类引用。 

注:发生向下转型可能会发生类型转换异常,使用instanceof关键字检查。

用法: 引用名称 instanceof 类;   返回类型是布尔值(false、true),表示该引用指向的本质是不是该类的对象。

public class Test {
    public static void main(String[] args) {
        Animal animal=new Dog();
        Animal animal1=new Animal();
        System.out.println(animal instanceof Dog);
        System.out.println(animal1 instanceof Dog);
    }
}

三、抽象类

抽象类:是普通类的超集,只是比普通类多了一些方法。抽象方法所在的类必须是抽象类,子类继承了抽象方法(子类是普通类)。定义抽象类和抽象方法时,使用abstract关键字。 

1、抽象方法:只有函数声明,没有函数实现的方法。本地方法也没有方法体,但不是抽象方法。

2、若一个类使用abstract声明为抽象类,无法通过该类实例化对象,哪怕该类中没有抽象方法,要产生对象,只能通过子类向上转型变为抽象父类的引用。

例:人类抽象,Person per = new Person();  // error

 Person per = new Chinese; // right

3、子类继承了抽象类,就必须强制子类(子类是普通类)覆写抽象类中的所有抽象方法,也满足单继承权限。

4、抽象类虽然无法直接实例化对象,但也存在构造方法。

四、接口

接口中只有全局常量和抽象方法。关键字:interface声明接口,子类使用implements实现接口。

1、接口表示具备某种行为 / 能力,实现接口时不是“ is a”关系,而是具备行为或能力。例如:相机是手机的子类,相机可以拍照(具备拍照的能力)。

2、接口表示一种行为或者规范,子类实现接口必须覆写所有的抽象方法。

3、接口中,public abstract、static final可省略,只保留最核心的方法返回值、方法参数列表、名称即可。

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值