1 / 31

SICStus Objects

SICStus Objects. Objektum orientált kiterjesztés a SICStus Prolog nyelvhez Pereszlényi Attila e-mail: p-attila@freemail.hu Az előadás anyaga letölthető: http://www.hszk.bme.hu/~pa310/progs/files/SICStusObjects.ppt

lynna
Download Presentation

SICStus Objects

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. SICStus Objects Objektum orientált kiterjesztés a SICStus Prolog nyelvhez Pereszlényi Attila e-mail: p-attila@freemail.hu Az előadás anyaga letölthető: http://www.hszk.bme.hu/~pa310/progs/files/SICStusObjects.ppt A példaprogramok letölthetőek: http://www.hszk.bme.hu/~pa310/progs/files/SICStusObjects.pl

  2. Bevezetés A SICStus Objects a prototípusokon alapszik. A prototípus egy objektum, amely a modellezendő világ egy entitása. Felhasználható arra, hogy belőle további objektumokat származtassunk, amelyek öröklik valamely tulajdonságait a prototípusnak, és amelyek maguk is prototípusok lehetnek. A két lehetséges eszköz ennek megvalósítására az öröklés és a delegáció. Egy objektum prolog predikátumok halmaza. A SISCtus Objects ennek alapján a SICStus modul rendszere kiterjesztésének tekinthető, és ez implementációs szinten is igaz. Egy objektum predikátumai lehetnek attribútumok vagy metódusok. Egy objektum lehet statikus vagy dinamikus, lehet definiálva a forrásban vagy létre lehet hozni dinamikusan a program futása során. Metódusok is lehetnek statikusak vagy dinamikusak.

  3. SICStus Objects library • A könyvtár betöltéséhez az alábbi szükséges: • | ?- use_module(library(objects)). • Ez az alábbi operátorokat (újra)definiálja: • :- op(1200, xfy, [ & ]). • :- op(1198, xfx, [ :- ]). • :- op(1198, fx, [ :- ]). • :- op(550, xfx, [ ::, <: ]). • :- op(550, fx, [ ::, <: ]).

  4. Objektum deklaráció Egy objektumot a következőképpen deklarálhatunk: objektum-azonosító :: { predikátum-1 & predikátum-2 & : predikátum-n }. Itt az objektum-azonosító egy prolog kifejezés (atom, vagy funktor(V1,…,Vn) alakú, ahol Vi változó), predikátum-i pedig egy metódus vagy attribútum. Megjegyzés: Minden predikátumra meghívódik az expand_term/2 eljárás, ez előtt pedig a method_expansion/3 kampó eljárás.

  5. Metódus deklaráció 1/4 Egy metódus klózait hasonlóan kell deklarálni, mint a Prolog klózokat, lehet szabály, tényállítás, ill. megengedett „catch-all” klózt használni utolsó klózként. A „catch-all” olyan klóz, aminek a feje egy Prolog változó, és minden olyan üzenetre illik, amely nem illik egyetlen előző klózra sem. Szabály törzsében lévő célsorozat az alábbi normál Prolog vezérlési szerkezet lehet:

  6. Metódus deklaráció 2/4 Szabály törzsében lévő célsorozat lehet még:

  7. member/2 -t importáljuk … …majd utána a forrás modulból hívjuk. Ebben az objektumban definiált metódusra hivatkozunk. Metódus deklaráció 3/4, példa 1/2 list_object :: { :- :use_module(library(lists), [member/2]) & append([], L, L) & append([X|L1], L2, [X|L3]) :- :: append(L1, L2, L3) & member(X, L) :- :member(X,L) & length([], 0) & length([_|L], N) :- :: length(L, N1), :(N is N1+1) }.

  8. Metódus deklaráció 4/4, példa 2/2 Attribútumok megadása tényállítással: Jobb megoldás attributes használatával: apt_1 :: { super(apartment) & street_name(’York’) & street_number(100) & wall_color(white) & floor_surface(wood) }. apt_1 :: { super(apartment) & attributes([ street_name(’York’), street_number(100), wall_color(white), floor_surface(wood)]) }. Megjegyzés: Az attributes-szal megadott attribútumokat hatékonyan lehet kezelni a get/1 és a set/1 metódusokkal.

  9. Generikus Objektumok 1/2 Nagy programok írásakor hasznosak lehetnek az újrahasznosítható objektumok. Egy lehetséges megvalósítási technika a generikus objektumok. Ez azt jelenti, hogy paraméterezhető prototípusokat definiálunk, amelyeknek a különböző paraméterekkel ellátott példányait különböző feladatokra lehet használni. Ezt azért lehet megtenni, mert az objektum azonosító összetett kifejezés is lehet. A kifejezésben lévő változók az objektum törzsében hozzáférhetőek. A paraméterezett objektumok azért is fontosak, mert velük elkerülhető az, hogy minden klóznak - ami egy adott kontextusban van - adnunk kelljen plusz változókat, mert a paraméter az objektum törzsén belül egy globális változónak felel meg.

  10. A rat objektum a racionális számok összehasonlításáért felel. Az objektum paramétere. A paraméterben megadott objektummal összehasonlíttatjuk X-et és P-t. Generikus Objektumok 2/2, példa rat :: { (P/Q < R/S) :- :(P*S < Q*R) }. sort(Type) :: { :- :use_module(library(lists), [append/3]) & qsort([], []) & qsort([P|L], S) :- partition(L, P, Small, Large), qsort(Small, S0), qsort(Large, S1), :append(S0, [P|S1], S) & partition([], _P, [], []) & partition([X|L1], P, Small, Large) :- ( Type :: (X < P) -> Small = [X|Small1], Large = Large1 ; Small = Small1, Large = [X|Large1] ), partition(L1, P, Small1, Large1) }. Egy futási példa: | ?- sort(rat) :: qsort([23/3, 34/11, 45/17], L). L = [45/17,34/11,23/3]

  11. Self A SICStus Objects-ben minden metódus egy objektum kontextusában fut. Ez nem feltétlenül az a statikus objektum, amelyben a metódus deklarálva van. Az aktuális környezeti objektum (Self) arra szolgál, hogy meghatározzuk a hozzáférhető attribútumokat és metódusokat. Az ezt megvalósító mechanizmust dinamikus kötésnek nevezzük. A környezeti objektumhoz hozzáférni a self(S) metódussal lehet, ahol S egyesítődik az objektummal. A a környezeti objektumra hivatkozni lehet még a self konstanssal.

  12. Üzenet küldés és delegáció 1/3

  13. Minden olyan üzenetre illik, ami nem volume vagy density. Az üzenetet tovább delegálja. Az üzenetet továbbküldi. Üzenet küldés és delegáció 2/3, pl.1 physical_object :: { volume(50) & density(100) & weight(X) :- volume(V), density(D), :(X is V*D) }. a :: { volume(5) & density(10) & Method :- physical_object <: Method }. b :: { volume(5) & density(10) & Method :- physical_object :: Method }. Egy futási példa: | ?- a :: weight(X), b :: weight(Y). X = 50 Y = 5000

  14. Self-nek küldünk üzenetet. Self-re hivatkozhatunk a self konstanssal. Üzenet küldés és delegáció 3/3, pl.2 Az előző physical_object definícióval ekvivalens: physical_object :: { volume(50) & density(100) & weight(X) :- self(S), S::volume(V), S::density(D), :(X is V*D) }. physical_object :: { volume(50) & density(100) & weight(X) :- self::volume(V), self::density(D), :(X is V*D) }.

  15. Öröklődés Szülő osztályt definiálni a super/2 metódussal lehet az objektum törzsén belül. (super(Super) metódust is lehet használni, ez azonban át fog íródni super(Super, []) alakúra.) A super/2-vel deklarált objektumok lesznek a közvetlen szülei az objektumunknak, ezektől fogja örökölni a metódusokat. Ha egy gyerek objektumban olyan metódust definiálunk, amely valamelyik szülő objektumban már van, akkor a szülő objektumban lévő klózok a gyerek számára láthatatlanok. Ha azt szeretnénk, hogy egy metódus úgy legyen értelmezve, mint a klózai összessége a gyerek objektumban és az egész felette lévő hierarchiában, akkor ezt megtehetjük a szülő objektumnak delegált üzenet segítségével. Ezt unió öröklődésnek nevezzük. A super/2 második argumentuma egy lista, az ebben a listában megadott metódusokat a gyerek osztály nem fogja örökölni. Ezt differenciális öröklődésnek nevezzük.

  16. Öröklődés, példa Állatok osztályozása: Futási példa: | ?- penguin :: motions(M). M = walk ; M = swim ; no (Gyerek metódusa felüldefiniálja a szülőjét.) animal :: {}. bird :: { super(animal) & skin(feather) & habitat(tree) & motions(fly) }. penguin :: { super(bird) & habitat(land) & motions(walk) & motions(swim) & size(medium) }. | ?- penguin :: skin(S). S = feather ; no (Gyerek örökli a szülő metódusait.)

  17. Többszörös öröklődés Több szülő objektumot a super/2 többszöri alkalmazásával adhatunk meg. Például: john :: { super(sportsman) & super(professor) & : }. Ekkor a szülő objektumok prioritást kapnak abban a sorrendben, ahogy definiálva lettek a super/2-vel. A fenti példában a sportsman dominálja a professort, ami azt jelenti, hogy ha mindkettőben van azonos metódus, akkor a gyerek objektumból a sportsman metódusa fog látszani.

  18. object, super/1 és sub/1 A SICStus Objects-ben létezik egy előre definiált objektum, amit object-nek hívnak, és amiben több hasznos és általános célú metódus van implementálva. Az object szolgáltatásaihoz úgy célszerű hozzáférni, hogy minden objektumot ebből örököltetünk, azaz az objektumok legősibb őse object kell legyen. Két hasznos object által adott metódus a super/1 és a sub/1, amivel az objektum hierarchiát lehet bejárni. (Ez a super/1 nem ugyanaz, mint öröklődésnél használt, mert az mindig átíródik super/2 alakúra.) A super/1 a Self közvetlen szüleit adja vissza, míg a sub/1 a közvetlen gyerekeit. Az előző példa esetén: | ?- john :: super(S), S :: sub(john). S = sportsman ; S = professor ; no

  19. A super kulcsszó A super konstans arra használható, hogy adott objektum legnagyobb prioritású szülőjének üzenetet küldjünk vagy delegáljunk. Ezt a következő hívásokkal tehetjük meg: super :: method, vagy super <: method Példa:Tegyük fel, hogy John-nak három id_card-ja van. Az egyik megmondja, hogy John melyik klubban sportol, ez a sportsman-ban van definiálva, a másik megmondja, hogy melyik egyetemen dolgozik, ez a professor-ban van definiálva, a harmadik pedig a személyigazolványa, ami a john-ban van definiálva. Ha a john-ban szerepel az alábbi: m1(X) :- super <: id_card(X) & Akkor kérdezhetjük a következőt: | ?- john :: m1(X). X = johns_club ; Ami visszaadja a legnagyobb prioritású szülő id_card-ját.

  20. Példa unió öröklődésre Adott az előző john osztály a három id_card-dal, és most azt szeretnénk, hogy egy kérdésre visszakapjuk John összes id_card-ját. Ezt a következőképpen tehetjük meg: Ekkor az alábbi kérdés visszaadja az összes id_card-ot: | ?- john :: m2(X). X = johns_personal_id; X = johns_club ; X = johns_university ; Definiáljuk john-ban az alábbi m2/1 metódust: m2(X) :- (self(S); super(S)), S <: id_card(X) & Vagy felvesszük az alábbi klózt john-ban az id_card-ja után: id_card(X):- super(S), S <: id_card(X) & Ekkor az alábbi kérdés adja vissza az összes id_card-ot: | ?- john :: id_card(X). X = johns_personal_id; X = johns_club ; X = johns_university ;

  21. Dinamikus objektumok Az előzőekben látott objektumoknak futás közben nem lehet megváltoztatni a metódusait. Ezeket az objektumokat statikusaknak nevezzük. Ahhoz hogy a metódusokat meg tudjuk változtatni, az objektumot dinamikusnak kell deklarálni. Ez a dynamic tényállítás objektum törzsébe történő felvételével tehető meg. (Az egyetlen nem megváltoztatható metódus a super/2). Az objektumot az object-ből kell örököltetni, mert az valósítja meg a dynamic-ot. dynamic_object :: { super(object) & dynamic & : }.

  22. Dinamikus metódusok Ha azt akarjuk, hogy csak adott F/N funktorú metódusokat lehessen megváltoztatni, akkor megtehetjük, hogy ezeket dinamikusnak deklaráljuk, és az objektum statikus marad. some_object :: { super(object) & dynamic F/N & : }. Metódushoz új klózt felvenni, vagy régi klózt eltávolítani az assert/1 és retract/1 metódusokkal lehet, úgy mint a normál SICStus Prolog predikátumok esetében. Használható még az augment/1, aminek a paramétere { sentence-1 & ... & sentence-n } alakú. Ez az összes sentence-i-t felveszi az objektum törzsébe.

  23. statikus metódusok dinamikus metódus Dinamikus metódusok, példa 1/2 Könyvtárban lévő könyveknek objektumokat (book) feleltetünk meg, amelyekben tároljuk a könyv címét (title), szerzőjét (author), és a kölcsönzési információkat (history_item(Person, Status, Date), ahol Statusborrowed vagy returned). A kölcsönzési információk változtathatók kell legyenek. Egy tipikus könyv az alábbi lehet: book_12 :: { super(book) & title(‘The Art of Prolog’) & authors([‘Leon Sterling’, ‘Ehud Shapiro’]) & dynamic history_item/3 & history_item(‘Dan Sahlin’, returned, 92-01-10) & history_item(‘Dan Sahlin’, borrowed, 91-06-10) & : }.

  24. Felveszünk egy új tényállítást a többi elé, ami a könyv kikölcsönzött állapotát tárolja. Dinamikus metódusok, példa 2/2 Írjuk meg a book borrow/1 metódusát, aminek a segítségével a könyvek kikölcsönzését adminisztrálhatjuk! (Feltesszük, hogy a legelső history_item/3 jelzi a legutolsó tranzakciót, és hogy létezik egy date objektumunk, amiből az aktuális dátumot megkaphatjuk.) borrow(Person) :- history_item(_Person0, Status, _Date0), !, ( Status = returned -> date::current(Date), asserta(history_item(Person, borrowed, Date)) ; :display(‘book not available’), :ttynl ) &

  25. Újradeklaráljuk p/1-et dinamikussá. b-ben a dinamikus viselkedés öröklődött. Ha egy metódust újradeklaráltunk, akkor a szülőben lévő klózok elvesznek. Dinamikus tulajdonság öröklődése A gyermek objektumok öröklik a szüleik dinamikus viselkedését is. Tehát a szülőkben definiált dinamikus metódusok megtalálhatóak lesznek a gyermekben is, és a dinamikus viselkedésük is megőrződik. Példa: Futási példa:| ?- b::p(X). X = 1 ? ; X = 2 ? ; no a:: { super(object) & dynamic p/1 & p(1) & p(2) }. b :: { super(a) }. c :: { super(a) & dynamic p/1 }. | ?- b::asserta(p(3)). yes | ?- b::p(X).X = 3 ? ; X = 1 ? ; X = 2 ? ; no | ?- c::p(X). no

  26. Objektum létrehozása futási időben (new/1): +SomeObject :: new(?NewObject) NewObject-et létrehozza, aminek a szülője SomeObject lesz. +SomeObject :: new(?NewObject,+Supers) NewObject-et létrehozza, aminek a szülei a Supers-ben megadott objektumok lesznek. Supers vagy egy objektum azonosítokból alló lista, vagy egy objektum azonosító – nem örökölendő metódus lista párokból álló lista. Futási idejű objektumdefiníció 1/2 Az eddigi módszerekkel nem lehet futás közben létrehozni vagy megváltoztatni az objektum hierarchiát, mert a super/2 nem lehet dinamikus. Ezért az öröklődési viszonyok már fordítási időben rögzülnek. Igény lehet azonban arra, hogy a program futása során hozzuk létre az objektum hierarchiát, amire a SICStus Objects lehetőséget ad. (Ezt is az object valósítja meg.)

  27. Futási idejű objektumdefiníció 2/2 Megjegyzés 1: NewObject lehet atom, változó vagy struktúra, aminek az argumentumai változók. Megjegyzés 2: mivel new egy üzenet, amit a SomeObject-nek küldünk, ezért értelmes a new(?NewObject) használata, ami NewObject-et úgy hozza létre, hogy Self lesz a szülője. Megjegyzés 3: A futási időben létrehozott objektumok mindig dinamikusak. Megjegyzés 4: A metódusokat ugyan úgy lehet létrehozni vagy megváltoztatni, mint a statikus objektumok dinamikus metódusait. Példa (objektumok létrehozása): | ?- object :: new(vehicle), vehicle :: new(moving_van), moving_van :: new(truck). Yes | ?- truck :: super(X), vehicle :: sub(X). X = moving_van ; no Metódusok felvétele: | ?- vehicle :: assert(fuel_level([])), vehicle :: assert(oil_level([])), vehicle :: assert(location([])), truck :: assert(capacity([])), truck :: assert(total_weight([])). yes

  28. assert-et újradefiniáljuk f-ben. Ekkor az assert régi funkciója elvész f számára. Ha p(x)-et vesszük hozzá, akkor kell majd kiírni. A super-ben még megvan az assert régi funkciója, ezért annak delegáljuk az üzenetet, hogy vegye fel p(x)-et. Azért kell delegálni, hogy Self ne változzon meg, és ezért f-ben legyen felvéve p(X). Ha nem p(X)-et vesszük hozzá, akkor a kiírás kivételével ugyanaz. Hozzáférés vezérelt programozás A hozzáférés vezérelt programozás alapja az, hogy különböző műveleteket elvégzünk, ha adott „hozzáférés operáció” történt. Nézzünk egy példát ennek a megvalósítására! Tegyük fel, hogy ki akarjuk írni azt, hogy „p hozzaveve”, akkor amikor az f objektumhoz hozzáveszünk egy p(X) tényállítást. f :: { super(object) & dynamic p/1 & p(0) & p(1) & assert(p(X)) :- !, super <: assert(p(X)), :display(‘p hozzaveve’), :ttynl & assert(M) :- super <: assert(M) & : }.

  29. object-ből öröklődik, további hasznos metódusokat valósít meg. Itt csak az ancestor/1-et használjuk. Mekkora vagyok? Mekkora a szülő osztályom? Mekkora vagyok én a szülő osztályomhoz képest? Visszaadja az objektum hierarchiában az első közös elemet. Az objektum őseit adja vissza a hierarchiában felfelé haladva. Példa – állatok osztályozása 1/2 animal :: { super(utility) & relative_size(S) :- size(Obj_size), super(Obj_prototype), Obj_prototype :: size(Prototype_size), :(S is Obj_size/Prototype_size * 100) & common(Obj, CObj):- (self(S1); ancestor(S1)), (S2 = Obj; Obj :: ancestor(S2)), :(S1 == S2), !, CObj = S1 }.

  30. Példa – állatok osztályozása 2/2 bird :: { super(animal) & moving_method(fly) & active_at(daylight) }. albatross :: { super(bird) & color(black_and_white) & size(115) }. kiwi :: { super(bird) & moving_method(walk) & active_at(night) & size(40) & color(brown) }. albert :: { super(albatross) & size(120) }. ross :: { super(albatross) & size(40) }. Futási példák:| ?- ross :: relative_size(R). R = 34.78260869565217 ? ; no | ?- albert :: common(kiwi, A), kiwi :: common(albert, A). A = bird ? ; no | ?- animal :: common(ross, A). A = animal ? ; no

  31. Felhasznált irodalom: SICStus Prolog User’s Manual

More Related