码上焚香

Yahocen

OOP原则、封装、继承、多态、接口和抽象类

14
2024-09-06

OOP原则(面相对象编程原则)

面相对象编程(Object-Oriented Programming, OOP)是一种编程范式,它强调使用“对象”来表示现实世界中的实体。Java 支持 OOP 的四个主要原则:

  • 封装:隐藏对象的具体实现细节,并对外提供访问接口

  • 继承:子类可以继承父类的属性和方法,实现代码复用

  • 多态:一个类实例可以被当作其父类类型来使用,从而实现动态绑定

  • 抽象:通过抽象类或接口来定义通用的行为模板,具体实现留给子类完成

封装(Encapsulation)

封装是指将数据和操作数据的方法绑定在一起,病对外部隐藏内部状态的过程。在 Java 中,封装通常是通过一下方式实现的:

  • 使用 private、protected 和 public 访问修饰符来限制成员变量和方法的可见性

  • 提供 getter 和 setter 方法来访问和修改私有成员变量

  • 控制对象和状态只能通用对象的方法来改变

继承(Inheritance)

继承允许一个类继承另一个类的属性和方法。这有助于实现代码复用和层次化的结构。在 Java 中,继承通过关键字 extends 实现:

public class Animal {
    public void eat() {
        System.out.println("Animal eats.");
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dog eats.");
    }
}

多态(Polymorphism)

多态性是指允许子类对象被当做父类对象类使用的能力。这是通过方法重载(Overloading)和方法覆盖(Overriding)来实现的:

  • 方法重载:同一个类中可以有多个同名但参数不同的方法。

  • 方法覆盖:子类中重新定义父类中的方法,以便提供不同的实现。

public class Animal {
    public void makeSound() {
        System.out.println("Animal makes sound.");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks.");
    }
}

接口(Interface)

接口定义了一组方法签名,没有具体实现。类可以通过实现接口来强制自己提供某些行为。接口在Java中使用 interface 关键字声明:

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks.");
    }
}

抽象类(Abstract Class)

抽象类不能被实例化,它主要用于提供一个包含部分实现的基础类,供子类继承和扩展。抽象类可以包含抽象方法(抽象方法没有具体实现),也可以包含具体方法(有实现的方法)。抽象类使用 abstract 关键字定义:

abstract class Animal {
    abstract void makeSound();
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks.");
    }
}

接口和抽象类的区别

尽管 Java 8 之后的接口可以包含默认方法和静态方法,使得接口的功能更为强大,但它们与抽象类还是有着本质的不同。接口主要用于定义一组行为规范,而抽象类则提供了行为的具体实现。接口强调的是“是什么”,而抽象类强调的是“怎么做”。

因此,在设计时,选择使用抽象类还是接口取决于具体的需求和设计目的。如果你需要定义一组行为规范,并允许不同类之间共享这些行为,那么接口是一个更好的选择。如果你需要提供部分实现,并允许子类在此基础上扩展,那么抽象类可能更适合。

接口于抽象类的主要区别

  1. 继承规则

    1. 抽象类:一个类只可以继承一个抽象类,并且可以同时实现多个接口

    2. 接口:一个类可以实现多个接口,但只能继承一个抽象类

  2. 构造函数

    1. 抽象类:可以有构造函数,用于初始化抽象类中的成员变量。

    2. 接口:一个类可以实现多个接口,但只能继承一个抽象类。

  3. 方法实现

    1. 抽象类:可以包含具体方法(既有实现的方法),可以包含抽象方法(无实现的方法)。

    2. 接口:传统上只包含抽象方法,可以包含默认方法(使用 default 关键字)和静态方法(使用 status 关键字)

  4. 访问修饰符

    1. 抽象类:方法可以有不同的访问修饰符(privateprotectedpublic)。

    2. 接口:方法默认是 public 的,而且是 abstract 的,除非制定了 defaultstatic

  5. 字段

    1. 抽象类:可以包含实例变量(成员变量),这些变量可以在字类中被继承或覆盖。

    2. 接口:只能包含常量(final 类型的变量),并且默认是 public static final 的。

示例

// 接口中包含默认方法
interface CanEat {
    default void eat() {
        System.out.println("Eating...");
    }
}

// 实现接口的类
class Dog implements CanEat {
    @Override
    public void eat() {
        System.out.println("Dog is eating...");
    }
}

// 抽象类示例
abstract class Animal {
    abstract void move();

    // 具体方法
    void sleep() {
        System.out.println("Sleeping...");
    }

    // 抽象方法
    void breathe();  // 必须在子类中实现
}

// 继承抽象类的子类
class Cat extends Animal {
    @Override
    public void move() {
        System.out.println("Cat moves...");
    }

    @Override
    public void breathe() {
        System.out.println("Cat breathes...");
    }
}