---
title: "反射"
date: "2026-04"
category: "设计模式与架构"
tags: ["设计模式与架构"]
description: "反射在有些地方看上去有点像是委托，但两者的差异还是蛮大的。委托的关键是编译器安全，而反射则是牺牲了编译时的安全检查，而带来了运行时的灵活性：它通过字符串来调用或取到指定的对象..."
source: "https://enriquemark.com/zh-hans/posts/%E5%8F%8D%E5%B0%84"
---

反射在有些地方看上去有点像是[委托](/zh-hans/posts/委托)，但两者的差异还是蛮大的。委托的关键是编译器安全，而反射则是牺牲了编译时的安全检查，而带来了运行时的灵活性：它通过字符串来调用或取到指定的对象，而可以让程序在运行时获取或修改任何代码内容——本质上来说，反射是一种「元操作」，用代码来操作代码，也是字面意义上的「反射」。

就拿我之前写的排程场景来说：假设我的排程是子类继承，下级只关心具体的job，但如果我的场景是判断有多少个job继承了基类——目前的做法是用反射去扫。在我刚了解到委托机制后，我的设想是，能不能在基类里面采用生命周期管理的模式，给子类包在一个run里，排程实际运行的是run，然后基类定义一个事件，这个run就是——到这一步时，我就突然发现了——事实上在基类里预定义的委托属性，在每次被继承并实例化时，这个属性都会重置，那这样的话事件队列就空了。

因此启动时直接扫描程序本身，去确认有多少子类继承了这个基类，才能交给排程框架去统一注册。否则要知道job有多少，就得先获取job，要获取job就得先注册，注册就得知道到底有多少job——最终就是没有任何job会被注册。实例化之前框架就得知道有几个，那我不可能在这之后才让job进事件，所以必须在启动前就知道，那这个只能靠反射去扫有多少类继承了base。这是一个类型发现问题，而不是委托所承载的对象之间的交互（订阅者通过发布者暴露的委托来操作）问题。
