方法与属性:对象的门面功夫
类不只有"普通方法"。就像一栋房子有正门、后门、还有只有房主才能开的密室——面向对象提供了多种方法和属性控制,让你精确地管理"谁能看到什么、谁能做什么"。
实例方法、类方法、静态方法
加载代码编辑器中……
| 类型 | Python | JavaScript | 用途 |
|---|---|---|---|
| 实例方法 | def method(self): | method() { } | 操作实例数据 |
| 类方法 | @classmethod + cls | 无直接对应 | 操作类本身 |
| 静态方法 | @staticmethod | static method() | 工具函数,不需要实例 |
JS 没有
@classmethod的等价物。Python 的类方法接收cls(类本身)作为第一个参数,可以在继承中正确指向子类。JS 的static方法通常用this(指向类本身)或直接用类名来实现类似效果。
Property:优雅的属性访问
有时候你想让"方法"看起来像"属性"——用户不需要知道背后有计算,只管用 .xxx 读取。
加载代码编辑器中……
| Python | JavaScript | |
|---|---|---|
| 定义 getter | @property | get propName() |
| 定义 setter | @propName.setter | set propName(val) |
| 使用 | obj.prop(看起来像普通属性) | obj.prop(一模一样) |
两种语言中,getter/setter 的使用方式完全一样——用户完全感觉不到背后有函数在运行。这就是"封装"的精髓:隐藏实现细节,暴露简洁接口。
私有成员
"这个属性不准外面的人碰!"——两种语言有不同的表达方式:
加载代码编辑器中……
| Python | JavaScript | |
|---|---|---|
| 约定私有 | _name(一个下划线) | _name(同样的约定) |
| 强制私有 | __name(名称改写,可绕过) | #name(真正私有,无法绕过) |
这里有个有趣的哲学差异:
- Python 信奉"我们都是成年人"——
_name是君子协定,告诉你"别碰",但不会阻止你。连__name也能通过_ClassName__name绕过- JS 的
#name是真正的私有——类外面无论如何都访问不到,编译器级别的强制执行
问问 AI
问 AI:"封装到底有什么好处?为什么不能让所有属性都公开?"
想象你写了一个银行账户类,余额属性可以被随便修改——用户直接 account.balance = 999999999。封装就是防止这种"抄近路"的行为,强制通过方法来操作数据,方法里可以加验证、记录日志等。
工厂方法模式
类方法和静态方法的一个经典用途是工厂方法——提供多种创建实例的方式:
加载代码编辑器中……
注意:Python 的 @classmethod 用 cls(...) 创建实例(这样子类也能正确工作),JS 的 static 方法直接用 new Color(...)。
🏋️AI 练习
创建一个 Rectangle 类:
- 构造函数接受
width和height area和perimeter作为 property / getter(不是普通方法)- 一个静态方法
square(side)返回正方形(等宽等高的矩形) width和height设置 setter,不允许负数
用 Python 和 JS 各写一版。测试:创建一个 3x4 矩形和一个边长为 5 的正方形,输出面积和周长。
小结
| 概念 | Python | JavaScript |
|---|---|---|
| 实例方法 | def f(self): | f() { } |
| 类方法 | @classmethod + cls | 无直接等价 |
| 静态方法 | @staticmethod | static f() |
| Getter | @property | get prop() |
| Setter | @prop.setter | set prop(v) |
| 约定私有 | _name | _name |
| 强制私有 | __name(可绕过) | #name(不可绕过) |
一句话:方法决定行为,属性控制访问。Python 靠约定和装饰器,JS 靠关键字和 # 语法。 封装不是多余的仪式感,它是代码长期可维护的基石。