PyPyBridge

面向对象:更少的仪式,更多的协议

record → dataclass,interface → Protocol,getter/setter → @property。Python 的 OOP 是减法。

18 分钟 · 右栏代码可点击「运行」


类与构造器:self 是显式的

Java
1public class Person {
2 private final String name;
3 private int age;
4
5 public Person(String name, int age) {
6 this.name = name;
7 this.age = age;
8 }
9 public String getName() { return name; }
10}
Python
1class Person:
2 def __init__(self, name: str, age: int):
3 self.name = name # 属性默认公开
4 self.age = age
5
6p = Person("Ada", 36)
7print(p.name) # 直接访问,没有 getter
  • self 等价于 this,但必须显式写在参数列表第一位;调用时不用传(p.name 自动绑定)。
  • 需要拦截读写时再加 @property,调用方代码完全不用改 —— 这就是为什么 Python 不鼓励一开始就写 getter/setter。

record → dataclass(一行消灭样板)

Java
1// Java 16+
2public record Point(int x, int y) {}
3
4// 旧写法:private 字段 + 构造器
5// + equals + hashCode + toString ≈ 40 行
Python
1from dataclasses import dataclass
2
3@dataclass
4class Point:
5 x: int
6 y: int
7
8# 自动生成 __init__ / __eq__ / __repr__
9p = Point(1, 2)
10print(p) # Point(x=1, y=2)
11# 不可变:@dataclass(frozen=True)

interface → Protocol(结构化,像 Go 但有静态检查)

Java
1interface Closer {
2 void close();
3}
4
5// 必须显式 implements
6class File implements Closer {
7 public void close() { ... }
8}
Python
1from typing import Protocol
2
3class Closer(Protocol):
4 def close(self) -> None: ...
5
6# 不需要继承:任何有 close() 的对象
7# 都满足 Closer(静态鸭子类型)
8
9def cleanup(c: Closer) -> None:
10 c.close()
  • Protocol 是 Go 隐式接口的 Python 版,但 mypy/pyright 会在静态阶段报错 —— 鸭子类型的编译期保险。
  • 需要运行时强制继承体系时才用 abc.ABC + @abstractmethod

继承与组合

Java
1public class Admin extends User {
2 public Admin(String name) {
3 super(name);
4 }
5 @Override
6 public String describe() {
7 return "Admin:" + getName();
8 }
9}
Python
1class Admin(User):
2 def __init__(self, name: str):
3 super().__init__(name)
4
5 def describe(self) -> str: # 覆写不需要注解
6 return f"Admin:{self.name}"
  • Python 遵循 EAFP 与组合优先,但继承语法本身很轻。多继承合法(MRO 顺序解析),Java 式 interface 多实现用 Protocol 组合。

注意

Java 习惯最大的坏味道把所有字段设为私有再生成 getter/setter。Python 惯例:直接公开属性,出现校验/派生逻辑时无痛升级为 @property

练一练

这张卡的示例代码已在游乐场中备好,改一改再运行。

在游乐场中打开