我正在寻找在运行时更改对象(或变量)的具体类的(开源)程序(或算法)的真实世界示例。
Java中此类行为的示例可能类似于下面的代码片段。
这里,在频繁插入和/或删除的上下文中表现良好的LinkedList
被更改为ArrayList
,在随机访问和迭代的上下文中表现良好。
List myList = new LinkedList();
/* Lots of inserts */
...
myList = new ArrayList( myList ); // 'change' into different class
/* Lots of iteration */
...
上面的Java示例在LinkedList
和ArrayList
之间进行了更改
表现。
但是,任何语言的示例,任何数据结构,使用任何技术*,以及出于任何原因都是受欢迎的。
*技术:简单简单,如上例所示,或者
在SmallTalk中使用become:
,在Python中使用__class__
,或者......
答案 0 :(得分:2)
您可能想要检查Smalltalk中become
方法的用例。该方法在运行时更改实例的类(或更改对实例的所有引用以引用不同的实例)
成为常用于增长/缩小集合,例如带有更多桶的字典,带有更大缓冲区的ByteArray等。可以从SmallInteger转换为BigIntegers(前者的大小有限,后者不是,但速度要慢得多),程序员甚至不会注意到(这是只有当你有可变整数时才合理,因此在Smalltalk中这不是怎么做的。但它可能是:)
另一种情况可能是将序列化表单中的实例加载回正在运行的系统,并将其类更新为最新版本。
答案 1 :(得分:2)
是的,请查看Smalltalk中的#become(例如麻省理工学院授权的Pharo.org)。
除了已经给出的例子之外,#become例如是有用的 你使用代理。想想ORM框架中的代理对象,比如 Glorp,您首先拥有代理以及何时需要真正的完整对象 它可以从数据库加载,很容易切换所有引用。
另一个例子是Pharo的Fuel框架。
答案 2 :(得分:1)
不知道这是否相关,但是间谍(部分嘲笑)的使用也符合你的描述(见http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Spy.html):
一个例子:
Person person = new Person();
person = spy(person);
doReturn("dominiek").when(person).getName();
在幕后创建一个子类,并根据用户'更改类的行为。行为声明。
答案 3 :(得分:1)
我只是在(Python) NLTK来源中遇到了这个实例。 LazyCorpusLoader(用于从磁盘加载数据集的对象)"变形"进入数据集本身。这是链接源代码的相关部分(创建数据集对象然后成为它):
corpus = self.__reader_cls(root, *self.__args, **self.__kwargs)
# This is where the magic happens! Transform ourselves into
# the corpus by modifying our own __dict__ and __class__ to
# match that of the corpus.
args, kwargs = self.__args, self.__kwargs
name, reader_cls = self.__name, self.__reader_cls
self.__dict__ = corpus.__dict__
self.__class__ = corpus.__class__
以下是此技术的基本原理(在同一文件的标题中):
LazyCorpusLoader是一个代理对象,用于代表a 语料库加载前的语料库对象。这允许NLTK 为每个语料库创建一个对象,但推迟相关的成本 加载这些语料库直到他们第一次 实际访问过。
因此,在这种情况下,在运行时更改类的目的是来模拟延迟评估。
(编辑:由于我从NLTK源(Apache 2.0许可证)逐字引用,这里是许可证本身的强制性链接:http://www.apache.org/licenses/LICENSE-2.0)