Java基础之类封装、继承、多态

简介: Java基础的封装、继承和多态是OOP的核心。封装通过访问控制(如private)隐藏类的内部细节,提供公共接口供外部交互。例如,`Person`类封装`name`和`age`,通过`getName()`和`setAge()`方法访问。继承允许子类(如`Dog`)继承父类(如`Animal`)的属性和方法,并可扩展或覆盖。多态使得父类引用可指向子类对象,调用方法时根据实际对象类型执行,如不同动物的`makeSound()`。接口实现多态提供了一种定义行为而不必关心实现的方式。向上转型(子类→父类)安全且默认,而向下转型(父类→子类)需类型检查以避免异常。

Java基础之类封装、继承、多态
上篇我们学习了Java的类和对象,类定义了对象的属性和方法,对象可以使用new关键字将类实例化。
今天来看面向对象编程(OOP)的三大基本也是其核心特性: 封装、继承与多态。
封装
在Java中,一个个的包(Package)包含了很多很多的类,每个类中都有各自的属性和行为,我们在使用的时候,可以通过import关键字引入包中的类。
然后实例化对象来调用其中的属性和方法,方法内部对调用者来说是不可见的,这个就是封装的概念。
封装是面向对象编程的基础,它将数据和行为组合在一个包中,并对对象的使用者隐藏了具体的实现细节。
也就是说我们通过定义类(Class)来实现了封装,同时使用private、public等关键字来实现对属性和方法的可访问权限控制。
public class Person {
private String name; // 私有属性,外部不能直接访问
private int age; // 私有属性,外部不能直接访问
// 构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公共方法,用于获取name属性
public String getName() {
return name;
}
// 公共方法,用于设置name属性
public void setName(String name) {
this.name = name;
}
// 公共方法,用于获取age属性
public int getAge() {
return age;
}
// 公共方法,用于设置age属性
public void setAge(int age) {
if (age >= 0) { // 设置年龄前进行校验
this.age = age;
} else {
System.out.println("年龄不能为负数");
}
}
// 行为方法
public void introduce() {
System.out.println("我的名字是:" + name + ",我今年" + age + "岁");
}
}
// 使用Person类
public class Main {
public static void main(String[] args) {
Person person = new Person("张三", 25);
person.introduce(); // 输出:我的名字是:张三,我今年25岁
person.setAge(-1); // 输出:年龄不能为负数
}
}
在上面的代码中,Person 类封装了 name 和 age 属性,以及与之相关的方法。通过将属性设置为私有(private),我们防止了外部直接访问这些属性,必须通过公共(public)方法来间接访问和修改,从而保证了数据的完整性和安全性。
这就是类的封装,调用者只需关注调用方法,不需要关注方法内部的实现,而且等到需要修改方法中实现的时候,也不会影响到调用者的代码逻辑。

继承(Inheritance)
继承其实就和现实中父与子的关系一样了,一个子类可以通过继承父类来获取父类的属性和方法。
子类可以有父类没有的拓展的属性和方法,也可以重写覆盖掉父类的方法。
现实中一个儿子只能有一个爹,但是一个爹能有多个儿子。父类和子类也一样,父类可以有多个子类继承,但是子类必须只能有一个父类。
// 父类
public class Animal {
    protected String name; // 保护级别属性,子类可以访问
    public Animal(String name) {
        this.name = name;
    }
    public void makeSound() {
        System.out.println("动物叫声");
    }
}
// 子类
public class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造函数
    }
    @Override
    public void makeSound() {
        System.out.println(name + "在汪汪叫");
    }
    public void fetch() {
        System.out.println(name + "在取东西");
    }
}
// 使用继承
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财");
        dog.makeSound(); // 输出:旺财在汪汪叫
        dog.fetch();     // 输出:旺财在取东西
    }
}
Dog 类继承自 Animal 类。Dog 类不仅拥有了 Animal 类的 name 属性和 makeSound 方法,还添加了一个新的方法 fetch。同时,Dog 类覆盖了 makeSound 方法,提供了自己的实现。
这就是继承的概念,父类也叫超类。注意protected关键和private一样也是用来访问控制的,意思是非公共但是子类也可以访问的权限。

多态(Polymorphism)
多态是面向对象编程中的一个核心概念,它允许我们以统一的接口来处理不同类型的对象。
在Java中,多态通常通过继承和接口实现。
上面我们知道了多个子类可以通过继承父类来继承父类的属性和方法,然后对父类的方法进行不同的覆盖实现。
多态的原理就是基于类的继承关系:当子类继承父类时,子类会继承父类的所有公有(public)和受保护(protected)的成员变量和方法。
这样,我们就可以使用父类的引用来指向子类的对象,而调用方法时,会根据实际的对象类型来执行相应的方法。
// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物叫声");
    }
}
// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪叫");
    }
}
// 子类
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵叫");
    }
}

// 使用多态
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();
        dog.makeSound(); // 输出:汪汪叫
        cat.makeSound(); // 输出:喵喵叫
    }
}
在上面的例子中,我们定义了一个父类 Animal 和两个子类 Dog 和 Cat。
子类都覆盖了父类的 makeSound 方法。
我们创建了 Animal 类型的引用,但实际上指向了 Dog 和 Cat 的对象。当我们调用 makeSound 方法时,会根据实际的对象类型来执行相应的方法,这就是多态的概念。
同样都是makeSound(),但是不同对象调用后就会有不同的实现,狗是汪汪,猫是喵喵。
还有一种多态的实现,是用接口实现。
接口是什么呢?
接口是一种抽象类型,它允许我们定义一组方法,而不需要实现这些方法。
通过用类来实现接口,类就可以使用接口类型的引用来指向实现接口的类的对象,而调用方法时,会执行类实现的相应方法。
所以接口就相当于一个父类,但是接口不需要像父类一样有自己的实现:
// 这样就定义了一个接口。
interface Flyable {
    //飞
    void fly();
}
// 实现接口的类
class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟儿飞翔");
    }
}
// 实现接口的类
class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机飞行");
    }
}

// 使用多态
public class Main {
    public static void main(String[] args) {
        Flyable bird = new Bird();
        Flyable airplane = new Airplane();
        bird.fly(); // 输出:鸟儿飞翔
        airplane.fly(); // 输出:飞机飞行
    }
}
我们定义了一个接口 Flyable 和两个实现接口的类 Bird 和 Airplane。在 Main 类中,我们创建了 Flyable 类型的引用,但实际上指向了 Bird 和 Airplane 的对象。当我们调用 fly 方法时,会根据实际的对象类型来执行相应的方法。

父类通常用来表示is-a关系,即子类是父类的一种。
接口用来表示can-do关系,即实现接口的类具有某种能力或行为。
子类只能有一个父类,但是实现类能实现多个接口

向上转型和向下转型的类型转换
上面实现多态的这种将子类对象引用赋值给父类引用的过程其实叫向上转型。当然实现类引用赋值给接口也一样。
这种转型是安全的,因为子类对象一定是父类的一个实例。向上转型会丢失子类特有的方法和属性,但仍然可以访问父类中定义的方法和属性。
还有对应的一种是向下转型,将父类对象引用赋值给子类引用的过程。这种转型是不安全的,因为父类对象可能不是子类的一个实例。如果直接进行向下转型,可能会导致 ClassCastException。因此,在向下转型之前,通常需要使用 instanceof 运算符来检查对象是否是子类的实例。
当然我们编写代码的时候一般肯定是知道,所以常用的就是直接强转:
if (animal instanceof Dog) {
    Dog dog = (Dog) animal; // 向下转型,前提是animal确实是Dog类型的实例
} else {
    // 不是Dog类型的实例,不能进行向下转型
}
向上转型和向下转型是多态性的两个方面。
向上转型是隐式的,通常在继承和接口实现中自动发生。
向下转型是显式的,需要使用强制类型转换,并且在使用前应该进行类型检查,以确保类型转换的安全性。
END
目录
相关文章
|
1天前
|
存储 Java
心得经验总结:浅谈Java类中的变量初始化顺序
心得经验总结:浅谈Java类中的变量初始化顺序
|
1天前
|
存储 Java
一篇文章讲明白JAVA类与对象(六)
一篇文章讲明白JAVA类与对象(六)
|
1天前
|
Java 机器人 程序员
深入理解Java中的类与对象:封装、继承与多态
深入理解Java中的类与对象:封装、继承与多态
|
1天前
|
Java 机器人 关系型数据库
Java中的类与接口:抽象与实现的艺术
Java中的类与接口:抽象与实现的艺术
|
2天前
|
Java
java反射-获取类的属性、构造方法、方法
java反射-获取类的属性、构造方法、方法
3 0
|
2天前
|
Java
java反射-获取类的Class对象方式
java反射-获取类的Class对象方式
4 0
|
2天前
|
存储 自然语言处理 Java
Java-File类与IO流(2)
Java-File类与IO流(2)
6 0
|
3天前
|
安全 Java
深度解读Java的继承和多态的特性
深度解读Java的继承和多态的特性
|
8天前
|
Java 数据安全/隐私保护
Java基础之类封装、继承、多态
Java基础之类封装、继承、多态
10 2
|
9天前
|
Java 数据安全/隐私保护 开发者
Java是一种完全支持面向对象编程的语言,其面向对象特性包括封装、继承、多态和抽象等
【6月更文挑战第18天】**面向对象编程(OOP)通过对象封装状态和行为,实现问题域的抽象。Java全面支持OOP,核心特性包括**: - **封装**:保护数据安全,隐藏内部细节。 - **继承**:子类继承父类属性和行为,促进代码重用。 - **多态**:一个接口多种实现,增强灵活性和扩展性。 - **抽象**:通过接口和抽象类抽离共性,简化复杂性。 **Java的OOP便于理解和解决复杂系统问题。**
20 3