2014-11-18 10 views
6

Szukam rzeczywistych przykładów (open source) programów (lub algorytmów), które zmieniają konkretną klasę obiektu (lub zmiennej) w środowisku wykonawczym.Zmiana implementacji/klasy w czasie wykonywania

Przykład takiego zachowania w Javie może wyglądać jak poniższy fragment kodu. Tutaj, LinkedList, który działa dobrze w kontekście częstych wstawień i/lub usuwa, zmienia się w ArrayList, który wykonuje się dobrze w kontekście losowego dostępu i iteracji.

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

Przykład Java powyżej zmian pomiędzy LinkedList i ArrayList dla dobra wydajność.

Jednak przykłady w dowolnym języku, dowolnej strukturze danych, przy użyciu dowolnej techniki * iz dowolnego powodu są mile widziane.

* Technika: jasne i proste jak w przykładzie powyżej, lub użyciu become: w Smalltalk lub __class__ w Pythonie, albo ...

+0

na walnym, pytanie, które prosi o biblioteki wyłączyć temat tutaj. Nie mogę również zrozumieć celu, za którym stoi twoje pytanie, ponieważ jasne jest, że rozumiesz, jakie są tego korzyści i jak można to zrobić na twoim przykładzie. – amit

+0

** Nie szukam biblioteki **, szukam "przykładowego kodu", tj. Innych scenariuszy, w których programiści zmieniają strukturę/klasy danych obiektu. Celem mojego pytania jest to, że muszę zbudować przypadek, że jest to dość powszechny wzorzec dla zapewnienia abstrakcji języka. – madewael

+1

Często tworzę tablice dynamicznie w fazie inicjalizacji i używam do tego ArrayList. Wtedy wiem, że żadne dalsze zmiany się nie dokonają. Zamienię je na zwykłą, starą tablicę, aby zmniejszyć obciążenie pamięci i nieco zwiększyć wydajność. – MrSmith42

Odpowiedz

1

nie wiem czy to jest istotne, ale może użycie szpiega (częściowe mocks) również pasuje do twojego opisu (patrz http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Spy.html):

Przykład:

Person person = new Person(); 
person = spy(person); 
doReturn("dominiek").when(person).getName(); 

Za kulisami podklasą jest tworzona i zachowanie klasy jest zmieniony Accor ding do deklaracji zachowania użytkowników.

2

Może zajść potrzeba sprawdzenia przypadków użycia dla metody become w Smalltalk. Metoda zmienia klasę instancji w środowisku wykonawczym (lub zmienia wszystkie odwołania do instancji, aby odwoływać się do różnych instancji).

Stanie się powszechnie używane do powiększania/pomniejszania kolekcji, np. Słownik z większą liczbą segmentów, ByteArray z większym buforem itd. Możliwe jest przekonwertowanie z SmallInteger na BigIntegers (poprzednia jest ograniczona, druga nie jest, ale jest znacznie wolniejsza), a programista nawet nie zauważy (jest to tylko uzasadnione jeśli masz zmienne liczby całkowite, więc nie jest tak jak w Smalltalk, ale może być :)

Innym przypadkiem może być ładowanie instancji z serializowanej postaci z powrotem do działającego systemu i aktualizowanie jej klasy do Najnowsza wersja.

2

Tak, spójrz na #become w Smalltalk (na przykład licencjonowany przez MIT Pharo.org).

Poza przykładami, które już podano #become jest na przykład przydatne, gdy pracujesz z serwerami proxy. Pomyśl o obiekcie proxy w strukturze ORM, takim jak Glorp, w którym najpierw masz serwer proxy, a kiedy potrzebny jest prawdziwy pełny obiekt, można go załadować z bazy danych i łatwo wszystkie odwołania zostaną zmienione.

Kolejnym przykładem jest struktura paliwowa w Pharo.

1

Właśnie natknąłem się na wystąpienie tego w (Python) NLTK źródło. Obiekt LazyCorpusLoader (obiekt używany do ładowania zbioru danych z dysku) "przekształca się" w sam zestaw danych.Oto odnośny fragment połączonego kodu źródłowego (tworzenie obiektu DataSet, a następnie coraz to):

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__ 

Oto uzasadnienie podane (w nagłówku tego samego pliku) do tej techniki:

LazyCorpusLoader to obiekt proxy, który służy do przechowywania obiektu korpusu przed załadowaniem korpusu. To pozwala NLTK na utworzyć obiekt dla każdego korpusu, ale odroczyć koszty związane z z ładowaniem tych korpusów, aż do pierwszego razu, że są one faktycznie dostępne.

Więc celem zmiany klasy w czasie wykonywania w tym przypadku jest emulować leniwy oceny.

(Edit: Od cytuję dosłownie z źródła NLTK (licencji Apache 2.0), tutaj jest obowiązkowe link do samej licencji: http://www.apache.org/licenses/LICENSE-2.0)