面向对象详解

2023/11/11 Java基础

# 1、面向过程与面向对象

  • 面向过程

面向过程编程(Procedural Programming)是一种以过程为中心的编程范式,它将程序看作是一系列的操作步骤,通过顺序执行和调用函数来实现任务。面向过程编程主要关注数据和函数的组织和处理,它将问题分解为一系列的步骤,每个步骤通过特定的函数实现。在面向过程编程中,数据和函数是分离的,函数通过传递参数来操作数据。常用的面向过程编程语言包括C和Fortran等。

  • 面向对象

面向对象编程(Object-Oriented Programming)是一种以对象为中心的编程范式,它将程序看作是一组相互协作的对象集合,通过定义对象和对象之间的关系来实现任务。面向对象编程主要关注对象和对象之间的交互和封装,它将问题分解为一组对象和对象之间的交互。每个对象都有自己的属性和方法,方法是对象的行为,属性是对象的状态。面向对象编程强调对象之间的继承、封装和多态等特性。常用的面向对象编程语言包括Java、C++和Python等。

  • 洗衣服案例

  • 面向过程:放入衣服 -> 启动洗衣机 -> 洗衣服 -> 关闭洗衣机
  • 面向对象:放入衣服 -> 洗衣机:启动、洗衣服、关闭

面向过程更注重实现的步骤,而面向对象更注重交互。有学过C语言可能更容易理解。

  • 面向对象的三大核心特性

  • 可重用性:代码重复使用,减少代码量,提高开发效率。面向对象的三大基本特征(继承、封装和多态)都围绕这个核心。
  • 可扩展性:指新的功能可以很容易地加入到系统中来,便于软件的修改。
  • 客观理性:能够将功能与数据结合,方便管理。

# 2、抽象

抽象思想的核心是将问题进行抽象和模型化。就是把同一类事物中共有的特征(属性)和行为(功能、方法)进行抽取,归纳,总结。

抽象的过程其实就是面向对象编程的核心思想。

抽象过程案例

  • 鸟、猪、猫、狗都是动物
  • 它们都有吃、跑、叫等行为,它们都有姓名、年龄、颜色等属性。
  • 可以将这些动物进行抽象和模型化,比如我定义了一个类Animal,它有属性name、age、color,有行为eat、run、cry。
  • Animal为类,name、age、color为属性,eat、run、cry为方法。都可以表示为鸟、猪、猫、狗。
  • 这样就实现了对同一类事物进行抽象和模型化。

看看具体实现

  • Animal类实现
public class Animal {
    private String name;
    private int age;
    private String color;
    
    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
    
    public void eat() {
        System.out.println(name + " is eating.");
    }
    
    public void run() {
        System.out.println(name + " is running.");
    }
    
    public void cry() {
        System.out.println(name + " is crying.");
    }
    
    // Getters and setters
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  • 测试类
public class Main {
    public static void main(String[] args) {
        Animal bird = new Animal("Bird", 1, "Yellow");
        System.out.println(bird.getName()); // Output: Bird
        bird.eat(); // Output: Bird is eating.
        
        Animal pig = new Animal("Pig", 2, "Pink");
        System.out.println(pig.getName()); // Output: Pig
        pig.run(); // Output: Pig is running.
    }
}
1
2
3
4
5
6
7
8
9
10
11

可以看到,Animal可以表示多种动物,只要创建了对象,就可以调用对应的方法。并且每个对象都有自己独有的属性,不会相互影响。这就是抽象的过程。

# 3、类

用来描述一类具有相同特征(属性)和相同行为(方法)的模板。

详细可以查看:

# 4、对象

对象(Object)是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。也就是类的实例,类是描述一类的抽象,对象是描述一个具体事物。比如Animal类,可以表示多种动物,而鸟对象,只能表示一种鸟。

# 4.1、成员变量

  • 定义在方法的外部,类的内部。使用范围是整个类
  • 不需要初始值
  • 存储在堆内存中(对象存在时才在存在)

# 4.2、局部变量

  • 定义在方法的内部或者某一个语句块的内部,适用范围仅限于方法内或者语句块内
  • 必须有初始值
  • 存储在栈内存中

# 4.3、成员方法

定义在类内部,方法前没有static关键字的方法

语法

访问修饰符 返回值类型 方法名称(参数列表){
    方法体
}
1
2
3

# 4.4、构造方法

对象一建立就会调用构造方法,可以创建对象,给成员变量(属性)初始化。

  • 方法名和类名相同
  • 没有返回值和void,没有return
  • 不能被static等关键字修饰
  • 可以方法重载(定义多个参数列表不同的构造方法)
  • 当一个类中没有写构造方法时,系统会默认给该类一个默认的无参构造方法。当自己定义构造方法后默认的构造方法就不存在了。
public class Animal {
    String name;
    int age;
    //构造方法
    public Animal(){
        System.out.println("------无参的构造方法------");
        name = "动物";
        age = 0;

    }
    public Animal(String name,int age){
        System.out.println("------有参的构造方法------");
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {
        //创建对象
        Animal a1 = new Animal();
        System.out.println(a1.name+","+a1.age);

        Animal a2 = new Animal("兔子",2);
        System.out.println(a2.name+","+a2.age);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 4.5、this关键字

this代表它所在方法所属对象的引用。哪个对象调用的this所在的方法,this就代表哪个对象。

# 5、封装

封装是面向对象编程的一个重要原则。它指的是将对象的内部状态(属性)隐藏起来,并通过公共方法来访问和修改这些状态。这样做的好处是可以控制对对象的访问,防止不合法的状态修改,并提供了一种更加可控的方式来与对象交互。

# 6、继承

继承是面向对象编程中的另一个关键概念。它允许你创建一个新类,该类可以继承另一个类的属性和方法。继承使得代码重用更容易,并允许你创建一个类层次结构,其中一个类(子类)继承另一个类(父类)的特征和行为。

public class BankAccount {
    // 共同的属性
    private String ownerName;
    private String accountNumber;
    private double balance;

    // 共同的方法
    public void deposit(double amount) {
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("余额不足!");
        }
    }

    public double getBalance() {
        return balance
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

继承BankAccount

public class SavingsAccount extends BankAccount {
    private double interestRate;

    public SavingsAccount(String ownerName, String accountNumber, double initialBalance, double interestRate) {
        // 调用父类构造方法初始化共同属性
        super(ownerName, accountNumber, initialBalance);
        this.interestRate = interestRate;
    }

    public void applyInterest() {
        double interest = getBalance() * interestRate;
        deposit(interest);
    }
}

public class CheckingAccount extends BankAccount {
    private double overdraftLimit;

    public CheckingAccount(String ownerName, String accountNumber, double initialBalance, double overdraftLimit) {
        // 调用父类构造方法初始化共同属性
        super(ownerName, accountNumber, initialBalance);
        this.overdraftLimit = overdraftLimit;
    }

    public void withdrawWithOverdraft(double amount) {
        if (amount <= getBalance() + overdraftLimit) {
            withdraw(amount);
        } else {
            System.out.println("超出透支额度!");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 7、多态

多态是面向对象编程的另一个重要概念。它允许不同类型的对象对相同的消息(方法调用)做出不同的响应。多态使得代码更灵活和可扩展,能够处理不同类型的对象,而无需知道其具体类型。

定义方法

public void printAccountInfo(BankAccount account) {
    System.out.println("账户信息:");
    System.out.println("账户持有者:" + account.getOwnerName());
    System.out.println("账户号码:" + account.getAccountNumber());
    System.out.println("当前余额:" + account.getBalance());
}
1
2
3
4
5
6

这个方法接受一个BankAccount对象作为参数,但实际上可以传递任何继承自BankAccount的对象,如储蓄账户或支票账户。这是多态的体现,同一个方法可以适用于不同类型的对象。

SavingsAccount savingsAccount = new SavingsAccount("Alice", "SA123", 1000.0, 0.03);
CheckingAccount checkingAccount = new CheckingAccount("Bob", "CA456", 500.0, 100.0);

printAccountInfo(savingsAccount); // 打印储蓄账户信息
printAccountInfo(checkingAccount); // 打印支票账户信息
1
2
3
4
5

在上面的示例中,我们分别传递了储蓄账户和支票账户对象给printAccountInfo方法,它能够正确地打印不同类型账户的信息。

Java中多态的体现,以下的一些都是多态的一个体现方式:

  • 方法重写(Method Overriding):子类可以重写父类的方法,通过使用父类引用变量访问子类重写的方法。这样可以实现基于父类引用调用子类的具体实现。
  • 接口的多态性:接口定义了一组方法的规范,类实现了接口后,可以通过接口引用变量来实现对这些类对象的多态引用。
  • 抽象类的多态性:抽象类可以包含抽象方法,子类可以重写这些方法,实现多态。

多态是一个形式的多样性体现,简单案例就是接口,通过new接口实例,来调用实现类的方法。