深入理解 Java 封装、继承与多态,附代码示例

1. 封装:用银行卡保护你的余额

什么是封装? 想象一下,你的银行卡和密码。银行不会直接把你的钱给任何人,而是通过 “密码验证” 这个方法,来控制对 “余额” 这个属性的访问。这就是封装。

在 Java 中,封装就是将类的状态信息(属性)隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法(getter 和 setter)来实现对内部信息的操作和访问。

核心作用:

  • 安全性: 保护对象的内部状态,防止被随意修改。
  • 可控性: 可以在 setter 方法中加入逻辑判断,对属性的修改进行限制。

代码示例:

java

运行

// 银行卡类
public class BankCard {
    // 属性:余额 (使用private修饰,只能在本类中访问)
    private double balance;

    // 构造方法:初始化余额
    public BankCard(double initialBalance) {
        // 可以在这里对初始余额进行合法性检查
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        } else {
            this.balance = 0;
            System.out.println("初始余额不能为负数,已设置为0。");
        }
    }

    // 方法:存钱 (setter的一种形式)
    public void deposit(double amount) {
        if (amount > 0) {
            this.balance += amount;
            System.out.println("成功存入 " + amount + " 元。");
        } else {
            System.out.println("存款金额必须大于0。");
        }
    }

    // 方法:取钱 (setter的一种形式)
    public void withdraw(double amount) {
        if (amount > 0 && amount <= this.balance) {
            this.balance -= amount;
            System.out.println("成功取出 " + amount + " 元。");
        } else {
            System.out.println("取款金额无效或余额不足。");
        }
    }

    // 方法:查询余额 (getter)
    public double getBalance() {
        return this.balance;
    }
}

// 测试类
public class TestBankCard {
    public static void main(String[] args) {
        BankCard myCard = new BankCard(1000); // 初始化一张有1000元的卡

        // 直接访问属性会报错,因为balance是private的
        // System.out.println(myCard.balance); // 编译错误

        // 通过方法来操作和访问
        myCard.deposit(500); // 存钱
        myCard.withdraw(200); // 取钱
        System.out.println("当前余额: " + myCard.getBalance()); // 查询余额

        // 尝试非法操作
        myCard.withdraw(2000); // 取款金额超过余额,操作失败
    }
}

2. 继承:动物家族的成员关系

什么是继承? 继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。

就像我们人类一样,孩子会继承父母的一些特征(如眼睛、鼻子),同时也会有自己独特的个性和能力。

核心作用:

  • 代码复用: 子类可以直接使用父类的属性和方法,无需重复编写。
  • 扩展性: 子类可以在父类的基础上,添加新的属性和方法,或者重写父类的方法。
  • 多态性: 继承是实现多态的基础。

代码示例:

java

运行

// 父类:动物
public class Animal {
    // 父类的属性
    protected String name; // 使用protected修饰,子类可以直接访问
    protected int age;

    // 父类的构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 父类的方法
    public void eat() {
        System.out.println(this.name + " 正在吃东西。");
    }

    public void sleep() {
        System.out.println(this.name + " 正在睡觉。");
    }
}

// 子类:狗,继承自动物类
public class Dog extends Animal {
    // 子类特有的属性
    private String breed; // 品种

    // 子类的构造方法
    public Dog(String name, int age, String breed) {
        // 调用父类的构造方法,初始化父类的属性
        super(name, age);
        this.breed = breed;
    }

    // 子类特有的方法
    public void bark() {
        System.out.println(this.name + " 正在汪汪叫。");
    }

    // 重写父类的方法(方法的名字和参数必须与父类完全一致)
    @Override
    public void eat() {
        System.out.println(this.name + " 正在啃骨头。");
    }
}

// 测试类
public class TestInheritance {
    public static void main(String[] args) {
        // 创建一个Dog对象
        Dog myDog = new Dog("旺财", 3, "中华田园犬");

        // 调用继承自父类的属性和方法
        System.out.println("我的狗叫 " + myDog.name + ",今年 " + myDog.age + " 岁。");
        myDog.sleep(); // 调用父类的sleep方法

        // 调用子类特有的方法
        myDog.bark();

        // 调用重写后的方法
        myDog.eat(); // 这里调用的是Dog类中重写的eat方法,而不是Animal类的
    }
}

3. 多态:同一个方法的不同表现

什么是多态? 多态是指同一个行为,对于不同的对象,会有不同的表现形式。

比如,同样是 “说话” 这个行为,中国人说中文,英国人说英文,这就是多态。

在 Java 中,多态的实现方式主要有两种:

  1. 方法重写(Overriding): 子类对父类的方法进行重新定义。
  2. 方法重载(Overloading): 在同一个类中,有多个方法名相同但参数列表不同的方法。

核心作用:

  • 灵活性: 可以用统一的接口来处理不同类型的对象。
  • 可扩展性: 新增一个子类时,不需要修改原来的代码。

代码示例(基于继承的代码):

java

运行

// 新增一个子类:猫
public class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }

    // 重写父类的eat方法
    @Override
    public void eat() {
        System.out.println(this.name + " 正在吃鱼。");
    }

    // 子类特有的方法
    public void meow() {
        System.out.println(this.name + " 正在喵喵叫。");
    }
}

// 测试类
public class TestPolymorphism {
    public static void main(String[] args) {
        // 创建不同的动物对象
        Animal myDog = new Dog("旺财", 3, "中华田园犬");
        Animal myCat = new Cat("咪咪", 2);

        // 调用同一个方法,但表现出不同的行为
        // 这里体现了多态:父类引用指向子类对象
        myDog.eat(); // 输出:旺财 正在啃骨头。
        myCat.eat(); // 输出:咪咪 正在吃鱼。

        // 多态的应用:统一处理不同类型的对象
        Animal[] animals = {myDog, myCat};
        for (Animal animal : animals) {
            animal.eat(); // 每个对象根据自己的类型,调用对应的eat方法
        }
    }
}

4. 综合案例展示

我们可以将封装、继承、多态结合起来,设计一个更加完整的程序。例如,一个简单的动物管理系统:

java

运行

// 动物管理类
public class AnimalManager {
    public static void manage(Animal animal) {
        System.out.println("管理一只动物:" + animal.name);
        animal.eat(); // 多态:根据animal的实际类型调用不同的eat方法
        animal.sleep();
    }

    public static void main(String[] args) {
        Animal dog = new Dog("旺财", 3, "中华田园犬");
        Animal cat = new Cat("咪咪", 2);

        // 统一管理不同的动物
        AnimalManager.manage(dog);
        AnimalManager.manage(cat);
    }
}

5. 常见误区提醒

  • 方法重写 vs 方法重载:
    • 重写(Overriding): 发生在父子类之间,方法名和参数列表必须完全一致。
    • 重载(Overloading): 发生在同一个类中,方法名相同,但参数列表(个数、类型、顺序)必须不同。
  • 父类引用指向子类对象: 这是多态的一种常见表现形式,但此时父类引用只能调用父类中定义的方法和属性,不能调用子类特有的方法和属性。
  • super 关键字: 用于在子类中调用父类的构造方法、属性和方法。

希望通过这篇文章,你对 Java 的面向对象三大特性有了更深入的理解。如果有任何疑问,欢迎在评论区留言交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值