2013-01-07 13 views
11

Robię badania w refleksji Smalltalk, i zastanawiałem się, czy możliwe było rozszerzenie pojedynczego obiektu, jak to byłoby możliwe na przykład w Ruby. Mam tu na myśli selektor, na który reagują tylko określone obiekty.Czy możliwe jest rozszerzenie pojedynczego obiektu w Smalltalk

Oto kod Ruby, który określa, co mam na myśli. Dla wyjaśnienia: w Ruby otwiera to wirtualną klasę dla tego obiektu i rozszerza ją o nową definicję. Najważniejszą częścią jest to, że nic nie zmienia się w definicji klasy!

o = Object.new 
o.instance_eval {def foo;puts "foo";end} 
o.foo #=> "foo" 

#however this will fail: 
m = Object.new 
m.foo #=> NoMethod error 

Dokładniej moje pytanie brzmi, czy jest to możliwe w standardowej Squeak/Pharo lub innych Smalltalk implementacjach, bez dodawania znaczących struktur lub kod na to zezwolić. Więc innymi słowy z regularnymi funkcjami odblaskowymi, które istnieją w Smalltalk.

Jako przykład można dodawać metody, usuwać metody, kompilować nowy kod do klasy, zmieniać zmienne instancji i prawie wszystko, ale nie znalazłem sposobu na rozszerzenie pojedynczego obiektu.

Test addInstVarNamed: #var. 
Test compile: 'var ^var'. 
t:= Test new. 
Test instVarNames. 
t instVarNamed: #var put: 666. 
t var. #=> 666 

Jeśli odpowiedź brzmi nie, to dlaczego. Nie szukam rozwiązania tego problemu, ale raczej rozumiem, dlaczego nie jest on w małym rozmiarze.

Odpowiedz

6

W Smalltalk nie ma wbudowanego sposobu postępowania w ten sposób. Smalltalk przestrzega zasady, że każdy obiekt należy do klasy, a jego zachowanie i kształt zależy od klasy. Dlatego możesz łatwo zmienić klasę (dodać inst vars, kompilować nowe metody, itd.), Ale to oznacza zmianę zachowania na wszystkie jego instancje. Istnieją jednak różne podejścia (zgodnie z zapachem Smalltalk) w celu osiągnięcia specyficznych dla instancji zachowań, takich jak Lekkie klasy, gdzie chodzi o stworzenie specjalnej (lekkiej) klasy dla konkretnej instancji i zastąpienie oryginalnej klasy niestandardowy. W rezultacie masz specjalną klasę dla każdej "specjalnej" instancji. AFAIK w Digitalk St Mechanizm dyspozytorski jest nieco bardziej elastyczny i pozwala na łatwe implementowanie zachowania opartego na instancjach (patrz czwarty link). Zostawię tu kilka linków, które mogą okazać się przydatne:

HTH

Edytuj:link opublikowany przez Hernana ("Debugowanie obiektów" przez Hinkle, Jonesa & Johnson) jest tym, do którego się odnosiłem i którego nie mogłem znaleźć.

+0

Przeczytałem już pierwsze łącze, ale może być trudno wytworzyć rzeczywisty pomysł za tym, co właśnie wyjaśniłeś. Na pewno sprawdzę inne linki. Znakomita odpowiedź. – froginvasion

+0

Może screencast (link 3D) da ci lepsze zrozumienie. Próbuję znaleźć * papier *, który wyjaśnia szczegółowo, jak lekkie lekcje działają, ale nie mogę tego znaleźć. Daj mi kilka minut :) –

+0

Niestety, nadal nie mogę go znaleźć. Dodałem jednak piąty link z doskonałym wyjaśnieniem, jak działa wyszukiwanie metody w Smalltalk i różne techniki używane do manipulowania dostarczaniem wiadomości. Odwołuje się także do lekkiego podejścia klasowego. –

1

W języku Ruby, o ile mi wiadomo, słownik metody dołącza się do obiektu.

W Smalltalk słownik metody jest powiązany z obiektem Class, więc na obrazie waniliowego Smalltalk nie można pisać rzeczy przypominających podobne do podobnych.

Po tym, istnieje kilka prototypowych bibliotek: this question's answers wspomnieć sporo.

+0

Wydaje mi się, że faktycznie masz obie w Ruby. Są również związane z obiektem klasy, ale eigenclass, który jest tworzony podczas rozszerzania obiektu, jest nową oddzielną klasą, która rozciąga się od klasy eigenclass klasy. Ale w każdym razie, sprawdzę link dzięki! – froginvasion

9

Specyficzne zachowanie instancji w Smalltalk zasadniczo polega na zmianie klasy wskaźnika i wywołania pierwotnego. Artykuł Boba Hinkle'a, Vicki Jones i Ralpha E. Johnsona opublikowany w The Smalltalk Report, tom 2 # 9, lipiec-sierpień 1993, zawiera wszystkie wyjaśnienia.

Przeportowałem oryginalny kod Lightweight klasy z wersji wydanej w 1995 roku przez Boba Hinkle'a dla VisualWorks 2.0. Źródło VisualWorks zawiera kod podzielony na trzy pakiety o nazwie "ParameterizedCompiler", "Punkt przerwania" i "Lekki". Przyczyną tego podziału było pragnienie posiadania oddzielnej i wielokrotnego użytku. Wszystkie mają oddzielne artykuły w czasopismach OOP.

My Squeak/Pharo port zawiera „wystąpienia Browser”, opartych na OmniBrowser (i więcej documentation here) ramy, które umożliwia przeglądanie i modyfikowanie instancje dodanie Lightweight zachowań poprzez klasycznym interfejsie Smalltalk przeglądarkę. Będzie działać w najnowszych wersjach Squeak 4.x przy niewielkim wysiłku lub bez wysiłku. Niestety infrastruktura Pharo zmieniła się zasadniczo z wersji < = 1.2, dlatego może zaistnieć potrzeba pracy nad najnowszymi wersjami.

Instances Browser with an instance modified

W VisualWorks, ze względu na głębokie zmiany w GUI VisualWorks od 2,0 do 7,3, większość narzędzi do zarządzają lekkie zajęcia nie zostały uwzględnione. Jeśli ktoś jest zainteresowany, mogę przesłać paczkę do VW 7,3

Instances Browser in VisualWorks

Podstawowy skrypt do testowania lekkie zajęcia wyposażony jest:

| aDate | 
aDate := Date today. 
aDate becomeLightweight. 
aDate dispatchingClass 
     compile: 'day ^42' 
     notifying: nil 
     ifFail: [self error]. 
aDate day inspect 
+0

... i to był papier, którego szukałem, ale nie mogłem go znaleźć. +1! –

2

colleage pracuje nowy refleksyjne API Pharo Smalltalk o nazwie Bifrost. możesz sprawdzić stronę Bifrost project.

Jego podejście popycha specyficzne dla instancji adaptacje w swoim rdzeniu. Wszystko dzieje się poprzez wiązanie metaobiektów do zwykłych obiektów w celu ich dostosowania. Mniejsze metaprzedsięwzięcia mogą się składać na gruboziarnisty metaobject wyższego poziomu, który definiuje sensowne adaptacje, np. metaobiekt profilowania, który będzie mierzył czas, w którym wykonywane jest każde wywołanie obiektu docelowego.

2

Jak zaznacza @ewernli, Bifrost w zasadzie czyni z Smalltalk obiektowy system refleksyjny. Wszystkie zmiany odblaskowe są kierowane najpierw na obiekty zamiast na mechanizm hybrydowy z klasami. Nadal możesz wykonywać wszystkie tradycyjne refleksje klasowe, ale nad refleksją obiektocentryczną. Co myślę, że jest istotne z tego nowego podejścia jest wiele aplikacji, które okazało się, że poprawia jaki opracowaliśmy i postrzegana system żywo:

Object-centric debugging całkowicie zmienia sposób debugowania poprzez skoncentrowanie się na przedmiotach i pozwala programiście na zachowaj interakcję z obiektami na żywo, zamiast wstawiać warunkowe punkty przerwania na poziomie kodu źródłowego.

Talents to składane dynamiczne jednostki wielokrotnego użytku, takie jak cechy, ale obiekty. Istnieje wiele innych aplikacji.

4

Skrzypiące dymki w dużym stopniu wykorzystują zachowanie i stan charakterystyczny dla obiektu. Jest to realizowane jako "uniclasses". Gdy utworzysz skrypt dla obiektu Etoys (instancja klasy Player), wówczas klasa obiektu zostanie zmieniona na "uniclass", czyli unikalną podklasę Player, która może mieć własne metody (odpowiadające skryptom Etoys) oraz zmienne instancji (odpowiadające zmiennym użytkownika Etoys).

Inne projekty oparte na piskach używają "anonimowych" uniclasses, które nie są wymienione jako podklasy w swojej nadklasie. Oznacza to, że są one prawie niewidoczne, ponieważ nie pojawiają się na przykład w Przeglądarce systemowej (podczas gdy w przeglądarce są wyświetlane jednolite w stylu Etoys).