面向对象编程(下)

目录

一、多态

1、向上转型

1.1 定义

1.2 向上转型举例

1.3 代码实例 

2、方法重写

 2.1 满足规则

2.2  注意事项

3、动态绑定

4、向上转型发生的时机 

4.1 直接赋值

4.2 返回值

4.3 传参

5、super关键字

5.1 含义及用法

5.2 super关键字与this关键字区别

6、多态的好处

二、抽象类

1、语法规则

2、注意事项 

3、抽象类作用

三、接口

1、语法规则

2、实现多个接口

3、接口间的继承

4、接口和抽象类对比


一、多态

1、向上转型

1.1 定义

        一个父类的引用指向一个子类的实例,通过父类引用调用父类和子类同名覆盖方法。此时,如果父类引用指向的子类对象不一样,调用这个重写的方法,表现得行为也不一样。

1.2 向上转型举例

例一:     Dog dog = new Dog("旺旺",14);

              Animal animal = dog;

例二:    Animal animal = new Dog("旺旺",14);

       向上转型之后,只能通过父类的引用访问父类自己特有的属性和方法,不能访问子类特有的方法和属性 

1.3 代码实例 

 // 先创建父类Animal 和子类Dog

class Animal{
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

}

// 向上转型并输出结果
public class test {
    public static void main(String[] args) {
        Dog dog = new Dog("旺旺",14);
        Animal animal = dog;
        System.out.println(animal.toString());
    }

}



运行结果:
  Dog{name='旺旺', age=14}
  

2、方法重写

 2.1 满足规则

  •  函数名称相同
  • 函数参数列表相同
  • 函数的返回值相同

2.2  注意事项

  •  普通方法可以重写, static 修饰的静态方法不能重写
  • 重写中子类的方法的访问权限不能低于父类的方法访问权限
  • private 修饰的方法不可以重写
  • 如果一个方法被 final 修饰称其为密封方法,也不可以重写

3、动态绑定

    动态绑定又称运行时绑定,是多态的基础

    通过父类引用调用父类和子类的同名覆盖方法,此时会发生动态绑定。绑定子类的同名函数

class Animal{
    public String name;
    public int age;

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

    public void eat(){
        System.out.println("吃东西!");
    }

}

class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override                                      //子类重写eat函数
    public void eat() {
        System.out.println("dog在吃!");
    }
}

public class test {
    public static void main(String[] args) {
        Animal animal = new Dog("旺旺",14);        //向上转型
        animal.eat();                             // 通过父类引用调用父类和子类同名覆盖方法
    }

}

 运行结果:

      dog在吃!

4、向上转型发生的时机 

4.1 直接赋值

Animal animal = new Dog("旺旺",14);

4.2 返回值


class Animal {                   //定义父类
    public String name;
    public int age;

    public Animal(String name, int age) {      //构造方法
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println("吃东西!");        //普通方法
    }
}
class Dog extends Animal {                     //定义子类

    public Dog(String name, int age) {
        super(name, age);
    }
    @Override                                   //重写eat方法
    public void eat() {
        System.out.println("dog在吃!");
    }
}


public class test1 {
    public static Animal func(){              //定义返回值为Dog 类型的方法
        Dog dog  =new Dog("旺旺",14);
        return dog;
    }

    public static void main(String[] args) {
        Animal animal = func();
        animal.eat();
    }
}

 运行结果:

      dog在吃!

4.3 传参


class Animal {
    public String name;
    public int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat(){
        System.out.println("吃东西!");
    }
}
class Dog extends Animal {

    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println(name+"在吃!");
    }
}

class Cat extends Animal {

    public Cat(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println(name+"在吃!");
    }
}

public class test1 {
    public static void func(Animal animal){
        animal.eat();
    }

    public static void main(String[] args) {
        Dog dog = new Dog("旺旺",14);              //new哪个就调用哪个子类的eat函数
        func(dog);
        Cat cat = new Cat("喵喵",3);
        func(cat);
    }
}

运行结果:

        旺旺在吃!
        喵喵在吃! 

5、super关键字

5.1 含义及用法

   (1)含义:  super 表示获取到父类实例的引用

   (2)用法

  • 使用了 super 来调用父类的构造器
public Bird(String name) {         super(name); }
  •     使用 super 来调用父类的普通方法
public class Bird extends Animal {         public Bird(String name) {               super(name);         }         @Override         public void eat(String food) {              // 修改代码 , 让子调用父类的接口 .               super.eat(food);         } }

5.2 super关键字与this关键字区别

区别 this super
1 概念 访问本类中的属性和方法 由子类访问父类的属性和方法
2 查找范围 先查找本类,本类没有则调用父类 直接调用父类
3 特殊 表示当前对象

6、多态的好处

  • 类调用者对类的使用成本进一步降低
  • 能够降低代码的“圈复杂度”,即避免使用大量的 if-else
  • 可扩展能力强

二、抽象类

1、语法规则

        抽象方法:该方法没有具体的实现,使用abstract修饰        

        抽象类:包含抽象方法的类称为抽象类

abstract class 类名 {         abstract public void 方法名(); }

2、注意事项 

(1)抽象类不能直接实例化(即不能new对象)

(2)抽象方法不能是 private 和 final 修饰的

(3)抽象类中可以包含其他的非抽象方法, 也可以包含字段. 这个非抽象方法和普通方法的规则都是一样的, 可以被重写, 也可以被子类直接调用

(4)如果一个普通类继承了抽象类,则普通类需要重写抽象类中的抽象方法

(5)一个抽象类A继承了另一个抽象类B,抽象类A中可以不重写抽象类B中的抽象方法。但是一旦抽象类A被继承后,继承的子类需要重写抽象类A和抽象类B中的所有抽象方法。

3、抽象类作用

   抽象类存在的最大意义就是为了被继承

三、接口

1、语法规则

interface 接口名 {      //定义接口         方法         属性 } class 类名 implements 接口名{          //实现接口 }
  • 接口名一般以 I 开头

  • 接口中的成员变量默认类型为: public static final
  •  接口中的方法一定是抽象方法, 因此可以省略 abstract
  • 接口中的方法一定是 public, 因此可以省略 public
  • 使用 implements 继承接口 . 此时表达的含义不再是 " 扩展 ", 而是 " 实现 "
  • 接口不能单独被实例化

2、实现多个接口

    定义一组接口, 分别表示 "会飞的", "会跑的", "会游泳的",再定义青蛙类,因为青蛙, 既能跑, 又能游,因此青蛙类需实现两个接口。

interface IFlying { 
 void fly(); 
} 

interface IRunning { 
 void run(); 
}
 
interface ISwimming { 
 void swim(); 
}

class Frog extends Animal implements IRunning, ISwimming { 
  public Frog(String name) { 
     super(name); 
  } 
  @Override 
  public void run() { 
     System.out.println(this.name + "正在往前跳"); 
  } 
  @Override 
  public void swim() { 
     System.out.println(this.name + "正在蹬腿游泳"); 
  } 
}

       IDEA 中使用 ctrl + i 快速实现接口 

3、接口间的继承

        接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字

4、接口和抽象类对比

区别 抽象类 接口
1 结构组成 普通类+抽象方法 抽象方法+全局常量
2 权限 各种权限 public
3 子类使用 extends关键字 implements关键字
4 关系 一个抽象类可以实现若干接口 接口不能继承抽象类,但是接口可以使用关键字extends关键字实现多个父接口
5 子类限制 一个子类只能继承一个抽象类 一个子类可以实现多个接口

上一篇:Serializable接口的作用;Externalizable自定义序列化和反序列化


下一篇:Java之Comparable(比较接口)