【问题标题】:Changing Implementation/Class at runtime在运行时更改实现/类
【发布时间】:2015-01-15 11:23:01
【问题描述】:

我正在寻找在运行时更改对象(或变量)的具体类的(开源)程序(或算法)的真实示例。

Java 中此类行为的一个示例可能类似于下面的代码片段。 这里,LinkedList 在频繁插入和/或删除的上下文中表现良好,被更改为ArrayList,在随机访问和迭代的上下文中表现良好。

List myList = new LinkedList(); 
/* Lots of inserts */
...
myList = new ArrayList( myList ); // 'change' into different class
/* Lots of iteration */
...

上面的 Java 示例在 LinkedListArrayList 之间变化 为了性能。

但是,任何语言、任何数据结构、使用任何技术*以及出于任何原因的示例都是受欢迎的。

*技术:简单如上例,或 在 SmallTalk 中使用 become:,在 Python 中使用 __class__,或者...

【问题讨论】:

  • 一般来说,关于图书馆的问题在这里是题外话。我也无法理解你的问题背后的目的,因为很明显你明白这样做有什么好处,以及如何从你的例子中做到这一点。
  • 我不是在寻找库,我在寻找“示例代码”,即程序员更改对象的数据结构/类的其他场景。我的问题背后的目的是,我需要证明这是一种足够常见的模式,可以为其提供语言抽象。
  • 我经常在初始化阶段动态创建数组并使用 ArrayList 这样做,然后我知道不会发生进一步的变化我将它转换为一个普通的旧数组以减少内存开销并提高性能位。
  • @MrSmith42 这对我的学习非常重要!这是私有软件还是公共软件?您是否有可能向我提供这些项目的指针?

标签: java performance algorithm data-structures


【解决方案1】:

您可能想要检查 Smalltalk 中 become 方法的用例。该方法在运行时更改实例的类(或将所有对实例的引用更改为引用不同的实例)

Become 通常用于扩大/缩小集合,例如具有更多桶的字典,具有更大缓冲区的 ByteArray 等。可以从 SmallInteger 转换为 BigIntegers(前者的大小有限,后者没有,但速度要慢得多),程序员甚至不会注意到(这只是合理的)如果你有可变整数,那么这不是在 Smalltalk 中这样做的方式。但它可能是:)

另一种情况可能是将实例从序列化形式加载回正在运行的系统,并将其类更新到最新版本。

【讨论】:

    【解决方案2】:

    是的,看看 Smalltalk 中的#become(例如 MIT 许可的 Pharo.org)。

    除了已经给出的示例之外,#become 例如在以下情况下很有用 你和代理一起工作。想想 ORM 框架中的代理对象,例如 Glorp 您首先拥有代理的位置以及何时需要真正的完整对象 它可以从数据库中加载,所有引用都可以轻松切换。

    另一个例子是 Pharo 中的 Fuel 框架。

    【讨论】:

      【解决方案3】:

      不知道这是否相关,但也许间谍(部分模拟)的使用也符合您的描述(请参阅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();
      

      在幕后创建一个子类,并根据用户的行为声明更改该类的行为。

      【讨论】:

        【解决方案4】:

        我刚刚在 (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 是一个代理对象,用于代表一个 语料库加载之前的语料库对象。这允许 NLTK 为每个语料库创建一个对象,但推迟相关的成本 加载这些语料库,直到他们第一次 实际访问过。

        因此,在这种情况下,在运行时更改类的目的是模拟惰性求值

        (编辑:由于我逐字引用 NLTK 源代码(Apache 2.0 许可证),这里是许可证本身的强制链接:http://www.apache.org/licenses/LICENSE-2.0

        【讨论】:

          猜你喜欢
          • 2023-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-15
          • 1970-01-01
          • 2014-06-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多