面向对象的三个基本特征分别是:封装、继承、多态

封装

把一个对象的属性隐藏在对象内部,不允许外界直接访问该对象内的信息,通常会提供一些对外的方法来间接操作属性。通过这种方式,对象的内部数据有了不同级别的保护,能够防止程序意外的改变和错误的使用对象的私有部分。

public class Dog {
    // 隐藏的属性
    private String name;

    // 对外的获取 name 方法
    public String getName() {
        return name;
    }

	// 对外的设置 name 方法
    public void setName(String name) {
        this.name = name;
    }
}
public class Cat {
    // 隐藏的属性
    private String name;

    // 对外的获取 name 方法
    public String getName() {
        return name;
    }

	// 对外的设置 name 方法
    public void setName(String name) {
        this.name = name;
    }
}

继承

两个或多个对象之间通常会存在一定数量的相同属性,例如:Dog 和 Cat 都有相同的属性字段 name,这时候就可以使用继承,将相同的属性字段放到父类 Animal 中,再有其他的动物就可以直接继承父类,同时就拥有了 name 属性,子类还可以继承父类的行为(方法)。通过继承,可以快速地创建新的类,能够很好的提高代码的重用和可维护性,提高开发效率。

继承通常存在以下特点:

  1. 子类 拥有 父类的所有属性和方法(含私有),但是子类无法直接访问父类私有的属性和方法,只能拥有,这就满足本文第一点封装的特性
  2. 子类除了拥有父类的属性和方法外,还可以自定义自己的属性和方法
  3. 子类可以使用自己的方式实现父类的方法(见第三点,多态)

将上面两个类使用继承的方式实现:

public class Animal {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Dog extends Animal {
    // 子类拥有了父类的 name 属性和 eat() 方法

    // 还可以定义自己的属性和方法
    private int age;

    public void play() {
        System.out.println("狗拿耗子!");
    }

    // ...省略 Getter、Setter
}
public class Cat extends Animal {
    // 子类拥有了父类的 name 属性和 eat() 方法

    // 还可以定义自己的属性和方法
    private String color;

    public void sleep() {
        System.out.println("猫在睡觉!");
    }

    // ...省略 Getter、Setter
}
public static void main(String[] args) {
    Cat cat = new Cat();
    cat.setName("小花猫");
    cat.setColor("花色");
    System.out.println(cat.getName() + "是" + cat.getColor()); // 小花猫是花色
    cat.eat(); // 动物吃东西
    cat.sleep(); // 猫在睡觉!

    Dog dog = new Dog();
    dog.setName("小黑狗");
    dog.setAge(3);
    System.out.println(dog.getName() + "有 " + dog.getAge() + " 岁"); // 小黑狗有 3 岁
    dog.eat(); // 动物吃东西
    dog.play(); // 狗拿耗子!
}

多态

父类的引用指向子类的实例,对于同一个行为(方法),不同的子类有不同的表现形式。上面的例子中,父类 Animal 中的 eat() 方法,就可以在子类中实现不同的表现形式。

多态通常存在以下特点:

  1. 对象类型和引用类型之间具有继承(类)或实现(接口)的关系
  2. 在调用方法的时候,到底运行父类的方法,还是子类的方法,必须在程序的运行期才能确定
  3. 子类重写了父类的方法,执行的就是子类覆盖的方法,否则,执行的是父类的方法(上例中,子类没有重写父类的 eat() 方法,所以结果是父类的内容)
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
public class Cat extends Animal {

}
public static void main(String[] args) {
    Cat cat = new Cat();
    cat.eat(); // 动物吃东西

    Dog dog = new Dog();
    dog.eat(); // 狗吃骨头
}