📄 一句话概括
专栏说 JS【执行时不受类约束】——实测给实例挂 3 个属性、给类挂 1 个方法,兄弟实例只能拿到类上那个;类是模板,但不是牢笼。
📝 本节和前面几节的关系
10.8 讲完职责分配的收益,这篇专栏换个角度:如果类本身都能随时改,那些设计原则还成立吗?
一、JS 的类约束为什么松
JS 是原型链语言:对象直接从别的对象继承,没有编译期的类型检查。 所以类只是一个语法糖,运行时的对象结构可以随时变。 这正是专栏标题说的【执行时不受类约束】。
二、实测:Python 也能演示
给实例 a 挂 3 个属性(nick/extra/another)——b 拿不到。
给类加 1 个方法 say_bye——b 立刻能用。
类文件一个字都没改,但运行时的行为变了。
三、灵活换来什么、失去什么
换来:不用为了加个字段去改类定义,测试里造数据特别方便。 失去:谁都可能改你——第三方库给你挂个属性,你排查半天。 还失去:看代码看不出对象长什么样,得跑起来才知道。
四、那设计原则还成立吗
成立,而且更重要:正因为约束是软的,才要靠人守住。 比如【只暴露必要的方法】——在这种语言里,私有靠约定,一旦公开就真的全公开。 所以语言越灵活,设计越重要;灵活性不是免费的,账单由维护者付。
五、动手 Demo:执行时不受类约束的JavaScript
给一个实例挂三个属性,再给类挂一个方法。 看另一个实例能拿到什么、拿不到什么。
class Person(object):
def __init__(self, name):
self.name = name
a, b = Person("阿甲"), Person("阿乙")
a.nick, a.extra, a.another = "小甲", 1, 2 # 只挂在 a 上
Person.say_bye = lambda self: "再见 " + self.name # 挂在类上
print(hasattr(b, "nick"), hasattr(b, "say_bye")) # False True
实跑输出:
--------------------------------------------------------------------
执行时不受类约束的JavaScript
--------------------------------------------------------------------
专栏说 JS【执行时不受类约束】。Python 其实也能演示这件事:实测给实例挂东西:
实例 a 挂上的属性 3 个(nick/extra/another)
类上后加的方法 1 个(say_bye)
b 有没有 nick False
b 能不能 say_bye True
类的定义改过吗 False(原文件没动)
语言 能随时加属性/方法吗 类必须在运行前定死吗
------------------------------------------------------------
JavaScript 能 不需要 class
Python 能(本文实测) 不需要(可动态造)
Java/C++ 不能 需要
**实测:a 挂 3 个属性、类上加 1 个方法,b 只能拿到类上加的那个。**
**这说明【类是模板,但不是牢笼】**——至少在这类语言里不是。
**专栏的意思不是说 JS 更好**:**没有约束换来灵活,也换来【谁都可能改你】**。
实测:a 挂的 3 个属性 b 拿不到(False),类上加的方法 b 立刻能用(True)。 类文件一个字都没改,运行时的行为却变了——这就是【不受类约束】。 灵活性不是免费的:语言越松,设计越要靠人守住。
30 秒实验
- 在 Python 里给一个实例动态挂方法,看它能不能拿到 self。
- 想想你的项目里,如果谁都能给对象加字段,排查问题会难多少。
常见误区
- 以为动态挂属性是高级技巧就该多用。它让对象长什么样变得不可预测。
- 以为语言松就不需要设计。越松越靠人守。
自测三问(点开对答案)
1. JS 的类约束为什么松? —— 它是原型链语言,类只是语法糖,运行时对象结构可随时变。 2. 实测结果如何? —— 实例 a 挂的 3 个属性 b 拿不到,类上加的 say_bye 方法 b 立刻能用。 3. 灵活性的代价是什么? —— 谁都可能改你的对象、看代码看不出对象形态;语言越松设计越要靠人守。- ☐ 下一章(第十一章 衍生:敏捷开发)
相关笔记
- 进行了职责分配的软件创建的奇妙世界 — 职责与结构的关系
- 类的功能之二:隐藏 — 私有靠约定的时候
- 原因之一:OOP结构复杂 — 复杂与灵活的取舍
- 🧩 面向对象是怎样工作的 · 索引