JavaSE-面向对象-OOP三大特征

49 阅读3分钟

核心思想: OOP不是语法糖,而是建模现实世界的思维范式。三大特征共同解决了复杂性管理问题。

🔒 1、封装 (保护内部)

本质定义: "Tell, Don't Ask"原则:对象暴露行为(方法),隐藏状态(数据)。不是简单的"private字段+public getter/setter",而是职责边界的划分。

关键认知:

  • 封装的是变化: 当业务规则变化时(如余额计算逻辑),客户端代码无需修改
  • 访问修饰符是手段,不是目的private/protected/public服务于封装原则
  • ❌ "用private+getter/setter就是封装" → ✅ "封装是暴露行为,不是暴露数据"
// 反模式:伪封装(只是字段私有化)
public class BadBankAccount {
    private double balance;
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
}

// 真正的封装:暴露业务行为,隐藏实现细节
public class BankAccount {
    private double balance;
    
    // 暴露业务行为,而非数据
    public void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
        this.balance += amount;
    }
    
    public boolean withdraw(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("金额必须为正");
        if (balance < amount) return false;
        this.balance -= amount;
        return true;
    }
    
    // 查询行为,而非直接暴露状态
    public double getAvailableBalance() {
        return balance * 0.9; // 假设10%是冻结资金
    }
}

🧬2、继承 (复用代码)

本质定义

"is-a"关系的代码表达,但更准确地说是契约复用。继承的目的是行为复用,而非仅仅是代码复用。

关键认知:

  • 继承是强耦合:子类依赖父类的实现细节,违反开放-封闭原则
  • 方法重写是契约:子类必须满足父类的前置/后置条件(Liskov原则)
  • Java单继承的哲学:避免菱形问题,强制设计者思考"真正"的is-a关系
// 继承的正确使用:Liskov替换原则
public abstract class PaymentMethod {
    public abstract boolean processPayment(double amount);
    
    // 模板方法模式:继承的核心价值
    public final boolean executePayment(double amount) {
        if (!validatePayment(amount)) {
            return false;
        }
        return processPayment(amount);
    }
    
    protected boolean validatePayment(double amount) {
        return amount > 0;
    }
}

public class CreditCardPayment extends PaymentMethod {
    private String cardNumber;
    
    @Override
    public boolean processPayment(double amount) {
        // 信用卡特定逻辑
        System.out.println("处理信用卡支付: " + amount);
        return true;
    }
    
    // 重写父类验证逻辑
    @Override
    protected boolean validatePayment(double amount) {
        return super.validatePayment(amount) && amount <= 10000; // 信用卡限额
    }
}

// 使用:完全不需要知道具体子类
public class PaymentProcessor {
    public void process(PaymentMethod method, double amount) {
        boolean success = method.executePayment(amount);
        System.out.println("支付结果: " + success);
    }
}

🤡3、多态 (灵活扩展)

本质定义

同一接口,多种实现。 多态的核心是运行时绑定,让程序在编译期不知道具体类型,而在运行时动态决定行为

关键认知

  • 多态 = 向上转型 + 动态绑定:父类引用指向子类对象,运行时JVM决定调用哪个方法
  • 方法表(vtable)机制:JVM通过对象头中的类指针找到方法表,实现动态分派
  • 多态是解耦的核心:高层模块依赖抽象,不依赖具体实现
  • @Override注解的价值:编译期检查,防止错误重写
// 多态的三种实现方式

// 1. 继承 + 方法重写(最常见)
public class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

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

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵!");
    }
}

// 2. 接口实现(更推荐)
public interface Flyable {
    void fly();
}

public class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟儿飞翔");
    }
}

public class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机起飞");
    }
}

// 3. 方法重载(编译时多态,非OOP核心)
public class Calculator {
    public int add(int a, int b) { return a + b; }
    public double add(double a, double b) { return a + b; }
}

// 多态的真正威力:开闭原则
public class Zoo {
    // 可以接受任何Animal子类,无需修改代码
    public void makeAllSounds(List<Animal> animals) {
        for (Animal animal : animals) {
            animal.makeSound(); // 运行时决定调用哪个方法
        }
    }
    
    // 通过接口实现更灵活的多态
    public void makeAllFly(List<Flyable> flyables) {
        for (Flyable flyable : flyables) {
            flyable.fly();
        }
    }
}