面向对象编程入门

本文是《Java 后端从小白到大神》修仙系列第零篇,正式进入Java后端世界,本篇文章主要聊Java基础,我们开始吧。

为什么要学习面向对象?

可能你在接触编程时就听说过"面向对象"这个词,但很多人即使学完课程,在实际开发中仍然对它感到困惑。面向对象思想是Java编程的核心,掌握它就等于掌握了Java编程的密码。本文将从基础概念讲起,帮助你真正理解面向对象编程的本质。

一、从面向过程到面向对象

1.1 面向过程编程(C语言)

在C语言中,数据和操作是分离的。我们使用 结构体定义数据 ,使用 函数定义操作 ,然后在main函数中按照顺序执行这些操作。

 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
#include <stdio.h>

// 定义学生结构体
struct Student {
    int number;  // 学号
    float score; // 成绩
};

// 函数声明
void inputStudentData(struct Student *s);
void printStudentData(struct Student s);

// 输入学生数据
void inputStudentData(struct Student *s) {
    printf("请输入学生学号: ");
    scanf("%d", &s->number); 
    printf("请输入学生成绩: ");
    scanf("%f", &s->score);
}

// 打印学生数据
void printStudentData(struct Student s) {
    printf("学号: %d, 成绩: %.2f\n", s.number, s.score);
}

int main() {
    int n;
    // 输入学生人数
    printf("请输入学生人数: ");
    scanf("%d", &n);

    struct Student students[n];
    // 输入每个学生的数据
    for(int i = 0; i < n; i++) {
        printf("\n输入第%d个学生的信息:\n", i + 1);
        inputStudentData(&students[i]);
    }
    
    // 打印所有学生信息
    printf("\n所有学生信息:\n");
    for(int i = 0; i < n; i++) {
        printStudentData(students[i]);
    }
    
    return 0;
}

特点

  • 数据和操作分离
  • 按照步骤顺序执行
  • 函数调用关系复杂,代码维护困难

1.2 面向对象编程(C++/Java)

C++和Java将数据和操作封装在一个类中,形成一个独立的单元。

  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
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#include <iostream>
#include <vector>
using namespace std;

class Student {
private:
    int number;
    float score;

public:
    // 构造函数
    Student(int number, float score) {
        this->number = number;  // 修正:拼写错误
        this->score = score;
    }

    // Getter和Setter方法
    int getNumber() {
        return number;
    }

    void setNumber(int number) {
        this->number = number;
    }

    float getScore() {
        return score;
    }

    void setScore(float score) {
        this->score = score;
    }
    
    // 打印学生信息
    void printInfo() {
        cout << "学号: " << number << ", 成绩: " << score << endl;
    }
};

// 学生管理类
class StudentManager {
private:
    vector<Student> students;

public:
    // 添加学生
    void addStudent(Student student) {
        students.push_back(student);
    }

    // 计算平均成绩
    float calculateAverageScore() {
        if (students.empty()) return 0;
        
        float sum = 0;
        for (Student student : students) {
            sum += student.getScore();
        }
        return sum / students.size();
    }
    
    // 打印所有学生信息
    void printAllStudents() {
        for (Student student : students) {
            student.printInfo();
        }
    }
};

int main() {
    StudentManager manager;
    int n;

    // 输入学生人数
    cout << "请输入学生人数: ";
    cin >> n;

    // 输入每个学生的数据
    for (int i = 0; i < n; i++) {
        int number;
        float score;
        cout << "\n输入第" << (i + 1) << "个学生的信息:" << endl;
        cout << "请输入学生学号: ";
        cin >> number;
        cout << "请输入学生成绩: ";
        cin >> score;

        Student student(number, score);
        manager.addStudent(student);
    }

    // 打印所有学生信息
    cout << "\n所有学生信息:\n";
    manager.printAllStudents();
    
    // 计算并打印平均成绩
    float average = manager.calculateAverageScore();
    cout << "\n学生的平均成绩: " << average << endl;

    return 0;
}

特点

  • 数据和操作封装在类中
  • 通过对象调用方法,代码更清晰
  • 为继承和多态打下基础

二、面向对象的核心概念

2.1 一切皆对象

在面向对象的世界中,一切都是对象。现实世界中的任何事物都可以看作一个对象,比如人、动物、书籍、汽车等。

2.2 面向对象的三大特性

封装

将数据和操作数据的方法封装在一起,形成一个独立的单元。通过访问修饰符(private、public等)控制数据的访问权限,提高代码的安全性和可维护性。

继承

子类可以继承父类的属性和方法,减少代码重复,提高代码的可扩展性。

多态

同一个方法在不同对象上有不同的实现。通过接口或抽象类实现多态,使代码更加灵活。比如:同样都是讲话,但你讲话和领导讲话,内容和方式都不一样吧,这就是多态。

2.3 类与对象的关系

  • :是对象的模板,定义了对象的属性和方法
  • 对象:是类的实例,通过new关键字创建

三、面向对象思想模型

3.1 现实世界与面向对象世界的映射

让我们以一个简单的例子来理解面向对象的思想模型:

classDiagram
    class Animal {
        +name: String
        +age: int
        +eat(): void
        +sleep(): void
    }
    
    Animal <|-- Dog
    Animal <|-- Cat
    
    class Dog {
        +bark(): void
    }
    
    class Cat {
        +meow(): void
    }

在这个例子中:

  • Animal是父类,定义了所有动物共有的属性和方法
  • DogCat是子类,继承了Animal的属性和方法,并添加了自己特有的方法
  • 当我们创建具体的狗或猫对象时,它们既具有动物的共性,又有自己的特性

3.2 多态的实现

多态允许我们使用父类类型的引用指向子类对象,实现统一的接口调用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 多态示例
Animal animal1 = new Dog();  // 向上转型
Animal animal2 = new Cat();

animal1.eat();  // 调用Dog的eat方法
animal2.eat();  // 调用Cat的eat方法

// 注意:父类引用只能调用父类中定义的方法
// animal1.bark();  // 编译错误
// 需要向下转型才能调用子类特有的方法
if (animal1 instanceof Dog) {
    Dog dog = (Dog) animal1;
    dog.bark();  // 调用Dog特有的方法
}

四、面向对象的实际应用

4.1 书籍分类示例

classDiagram
    class Book {
        +title: String
        +publisher: String
        +price: double
        +getInfo(): String
    }
    
    Book <|-- TechBook
    Book <|-- LiteratureBook
    Book <|-- NovelBook
    
    class TechBook {
        +field: String
        +getTechInfo(): String
    }
    
    class LiteratureBook {
        +genre: String
        +getLiteratureInfo(): String
    }
    
    class NovelBook {
        +type: String
        +getNovelInfo(): String
    }

4.2 实际开发中的应用

在实际开发中,面向对象编程的优势体现在:

  1. 代码复用:通过继承和组合实现代码复用
  2. 模块化:每个类都是一个独立的模块,便于维护和测试
  3. 可扩展性:通过继承和多态,轻松添加新功能
  4. 可维护性:封装使得代码结构清晰,易于理解和修改

五、总结

面向对象编程是一种编程思想,它将现实世界中的事物抽象为对象,通过封装、继承和多态等特性,使代码更加清晰、灵活和可维护。

核心要点

  • 类是对象的模板,对象是类的实例
  • 封装将数据和操作封装在一起
  • 继承实现代码复用和扩展
  • 多态提高代码的灵活性

通过学习面向对象编程,你将能够设计出更加模块化、可维护的Java应用程序。在后续的文章中,我们将深入探讨面向对象的具体实现和最佳实践。