面向对象编程与 Everything is object
从对象、类、封装和多态出发,理解面向对象编程与 Python 中“一切皆对象”的含义。
关键词oop · object-oriented · everything-is-object · java · python · programming-paradigm
建议先了解
- 函数与类基础
1. 这篇笔记解决什么问题
本篇解决两个在对话中多次混淆的概念:
- 面向对象编程(Object-Oriented Programming,OOP)到底是什么;
- “Everything is object” 到底是什么理念。
同时解释:Python 为什么既“一切皆对象”又是多范式语言;Java 为什么有 static 方法仍然是典型 OOP 语言;哪些语言更强调 OO,哪些语言主要采用其他范式。
2. 前置知识
- 函数、变量;
- class 与实例;
- 属性和方法。
3. 核心概念
3.1 面向对象编程(OOP)
OOP 主要回答:
程序应该如何组织?
核心思想是把系统抽象成一组具有状态和行为的对象,并让对象之间协作。
例如银行账户:
class Account:
def __init__(self, balance):
self.balance = balance
def deposit(self, money):
self.balance += money
对象模型:
Account 对象
├── 状态:balance
└── 行为:deposit()
程序员关注的问题从“我要依次调用什么函数”转向:
系统有哪些对象?
每个对象负责什么状态?
对象能做什么?
对象之间如何交互?
3.2 Everything is object
该理念主要回答:
程序运行时的“值”采用什么统一模型?
Python 中:
10 → int 对象
"hello" → str 对象
[1, 2] → list 对象
函数 → function 对象
类 → type/class 对象
模块 → module 对象
所以它是对象模型(object model)的理念,不是程序组织范式。
3.3 两者的核心区别
Everything is object
↓
“运行时的东西是什么?”
OOP
↓
“程序应该怎么组织?”
因此 Python 可以完全遵守 Everything is object,却写成过程式风格:
x = 10
y = 20
def add(a, b):
return a + b
print(add(x, y))
这里的数字和函数都是对象,但程序并没有围绕业务对象建模。
3.4 多范式语言(Multi-Paradigm Language)
Python 可以支持:
过程式(procedural)
面向对象(object-oriented)
函数式风格的一部分(functional style)
所以 Python 的设计特点是:底层对象模型统一,上层程序组织方式比较自由。
3.5 OOP 的典型机制
本次对话涉及:
- 封装(Encapsulation):相关状态和行为放在同一抽象单元;
- 继承(Inheritance):一个类型在已有类型基础上扩展;
- 多态(Polymorphism):统一接口可以对应不同具体实现。
例如:
class Dog:
def speak(self):
print("汪")
class Cat:
def speak(self):
print("喵")
for animal in [Dog(), Cat()]:
animal.speak()
调用端统一写 speak(),行为由具体对象决定。
4. 直观理解
可以用一个有限的类比:
- Everything is object:世界里的“材料”都采用统一的对象模型;
- OOP:你选择按“汽车、房子、道路”等对象及其责任组织工程。
材料统一并不意味着只能有一种组织方式。
5. 工作原理
5.1 过程式与面向对象
过程式:
balance = 100
def deposit(balance, money):
return balance + money
数据与操作数据的函数是分离组织的:
数据 → 函数 → 新数据
OOP:
account = Account(100)
account.deposit(50)
状态和行为围绕同一个对象组织。
5.2 Java 的经典入口为什么是 static
Java 经典入口:
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
}
}
main 在类中,但 static 表示无需先创建 Main 实例即可调用。
概念流程:
JVM
↓
加载 Main 类
↓
找到 static main
↓
进入程序
若入口必须是实例方法,JVM 在程序入口尚未开始前还需要先解决“创建哪个实例”的问题。
5.3 为什么有 static 仍然是 OOP
“面向对象语言”不等于:
每一行代码都必须属于具体对象实例。
Java 的核心建模机制仍大量围绕:
class / object
封装
interface
继承
多态
static 只是类级成员机制之一。
5.4 为什么不能简单说 Python 比 Java“更高级”
Python 更强调:
- 动态性;
- 对象模型统一;
- 多范式自由;
- 快速表达。
Java 更强调:
- 静态类型;
- 明确类/接口结构;
- 编译期检查;
- 工程约束。
这是设计取舍不同,不是简单的高低级关系。
6. 示例
示例:账户的两种写法
过程式:
balance = 100
def withdraw(balance, amount):
return balance - amount
balance = withdraw(balance, 20)
面向对象:
class Account:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
self.balance -= amount
account = Account(100)
account.withdraw(20)
这个例子说明 OOP 的核心不是“出现了对象值”,而是程序是否围绕对象责任、状态和行为组织。
7. 代码、命令或公式
Java 经典入口:
public static void main(String[] args)
本次对话只解释了 static 的入口意义,没有展开 JVM class loading 与 launch protocol 的完整细节。
8. 容易混淆的概念
| 概念 A | 概念 B | 核心区别 |
|---|---|---|
| OOP | Everything is object | 前者是编程范式,后者是运行时对象模型 |
| class | object | class 定义类型/行为,object 是具体实例 |
| instance method | static method | 前者绑定实例,后者属于类级别 |
| 支持 OOP | 只能 OOP | 多数现代语言可同时支持多种范式 |
| Java 是 OOP | Java 一切皆对象 | Java 是典型 OOP,但 primitive 等不是普通对象 |
| Python 一切皆对象 | Python 必须 OOP | Python 对象模型统一,但程序组织可过程式/函数式 |
9. 常见误区
误区:所有值都是对象,所以 Python 写什么都是 OOP
错误原因:把对象模型和编程范式混为一谈。
正确理解:Python 程序可以完全不定义业务 class,仍然建立在对象模型上。
如何验证:写一个只包含函数和数据流的 Python 程序。
误区:Java 有 static,所以不是真正面向对象
错误原因:把 OOP 错误定义成“任何代码都必须绑定实例”。
正确理解:OOP 看的是语言与程序的主要建模方式,允许存在类级工具与入口机制。
误区:除了 C,其他语言都是面向对象语言
错误原因:忽略编程范式的多样性。
正确理解:Haskell 偏函数式,Prolog 偏逻辑编程,C 偏过程式;Rust、Go 等也不完全采用传统 class/inheritance OOP 模型。
10. 与其他知识的关系
待建链接:函数式编程
待建链接:过程式编程
11. 可以亲手完成的验证
实验目标:对同一个小问题分别使用过程式与 OOP 实现。
任务:实现账户的存款、取款、余额查询。
- 过程式版本:余额作为数据传给函数;
- OOP 版本:余额放进
Account实例; - 比较状态归属、调用方式和扩展新行为时的变化。
实验不能证明:一个几十行例子的代码长度不能证明某范式在所有大型工程中一定更好。
12. 尚未解决的问题
- Smalltalk 的 message passing 如何比 Python/Java 更“纯 OO”未展开。
- Ruby 的对象模型与 Python 的差异未展开。
- 现代 OOP 中 composition、interface、trait 与继承的关系未讨论。
- Rust/Go 是否应被称为面向对象语言涉及定义边界,本次只做了粗略分类。
13. 自测问题
- OOP 主要回答什么问题?
- Everything is object 主要回答什么问题?
- 为什么 Python 可以“一切皆对象”但程序不采用 OOP?
- Java 为什么使用
static main? static为什么不否定 Java 的 OOP 属性?- Python 的“自由”和 Java 的“约束”分别体现在哪里?
参考答案
- 程序如何围绕对象、状态、行为和协作组织。
- 运行时值如何统一表示和参与对象系统。
- 因为对象模型决定值是什么,编程范式决定程序怎么组织。
- 让 JVM 在没有实例的情况下获得稳定程序入口。
- OOP 不要求所有代码都属于实例;Java 的主要建模机制仍是 class/object。
- Python 更强调动态、多范式和统一对象模型;Java 更强调静态类型、类/接口结构和编译期约束。
14. 一句话总结
OOP 是“如何组织程序”的方法,Everything is object 是“运行时值如何统一建模”的理念;两者可以同时存在,也可以彼此独立。