Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

SICStus Objects Objektum orientált kiterjesztés a SICStus Prolog nyelvhez Pereszlényi Attila Az előadás.

Hasonló előadás


Az előadások a következő témára: "SICStus Objects Objektum orientált kiterjesztés a SICStus Prolog nyelvhez Pereszlényi Attila Az előadás."— Előadás másolata:

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

2 2 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. Bevezetés

3 3 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, [ ::, <: ]). SICStus Objects library

4 4 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. Objektum deklaráció

5 5 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: :P, :Q Konjunkció :P; :Q Diszjunkció ! Vágó \+ Negálás :P -> :Q :P -> :Q; :R if(:P, :Q, :R) If-then-[else] ?A = ?B Egyesítés Metódus deklaráció 1/4

6 6 Szabály törzsében lévő célsorozat lehet még: :goal A forrás modulban lévő Prolog célsorozat hívása. m:goal Az m modulban lévő Prolog célsorozat hívása. goal A Self objektumnak elküldi a goal célsorozatot. ::goal Az objektumban definiált vagy öröklött metódusnak elküldi a goal célsorozatot. <:goal Az objektumban definiált vagy öröklött metódusnak delegálja a goal célsorozatot. object::goal object objektumnak elküldi a goal célsorozatot. object<:goalobject objektumnak delegálja a goal célsorozatot. Metódus deklaráció 2/4

7 7 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) }. 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

8 8 Attribútumok megadása tényállítással: apt_1 :: { super(apartment) & street_name(’York’) & street_number(100) & wall_color(white) & floor_surface(wood) }. Jobb megoldás attributes használatával: 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. Metódus deklaráció 4/4, példa 2/2

9 9 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. Generikus Objektumok 1/2

10 10 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 Small = [X|Small1], Large = Large1 ; Small = Small1, Large = [X|Large1] ), partition(L1, P, Small1, Large1) }. 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. Egy futási példa: | ?- sort(rat) :: qsort( [23/3, 34/11, 45/17], L). L = [45/17,34/11,23/3]

11 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 12 Üzenet küldés és delegáció 1/3 objektum :: üzenet :: üzenet Üzenet küldése. Küldéskor az üzenetnek megfelelő metódus a címzett objektum ( objektum ) kontextusában fut. Ekkor a Self az objektum ra állítódik. Ha a címzettet nem írjuk ki, akkor a címzett az az objektum lesz, ahol a célsorozat található. objektum <: üzenet <: üzenet Üzenet delegáció. Delegációkor az üzenetnek megfelelő metódus a delegáló objektum kontextusában fut. Fontos, hogy a delegáció nem változtatja meg a Self -et. Ha a címzettet nem írjuk ki, akkor a címzett az az objektum lesz, ahol a célsorozat található.

13 13 Ü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 }. Minden olyan üzenetre illik, ami nem volume vagy density. Az üzenetet tovább delegálja.Az üzenetet továbbküldi. Egy futási példa: | ?- a :: weight(X), b :: weight(Y). X = 50 Y = 5000

14 14 Ü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) }. Self -nek küldünk üzenetet. physical_object :: { volume(50) & density(100) & weight(X) :- self::volume(V), self::density(D), :(X is V*D) }. Self -re hivatkozhatunk a self konstanssal.

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

17 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 professor t, ami azt jelenti, hogy ha mindkettőben van azonos metódus, akkor a gyerek objektumból a sportsman metódusa fog látszani.

18 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 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 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: Definiáljuk john -ban az alábbi m2/1 metódust: m2(X) :- (self(S); super(S)), S <: id_card(X) & 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 ; 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 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 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 23 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 Status borrowed 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) & : }. statikus metódusok dinamikus metódus

24 24 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 ) & 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.

25 25 | ?- c::p(X). no | ?- b::p(X). X = 3 ? ; X = 1 ? ; X = 2 ? ; no 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: a:: { super(object) & dynamic p/1 & p(1) & p(2) }. b :: { super(a) }. c :: { super(a) & dynamic p/1 }. Futási példa: | ?- b::p(X). X = 1 ? ; X = 2 ? ; no Ú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. | ?- b::asserta(p(3)). yes

26 26 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.) Objektum létrehozása futási időben ( new/1 ): +SomeObject :: new(?NewObject) +SomeObject :: new(?NewObject,+Supers) NewObject -et létrehozza, aminek a szülője SomeObject lesz. 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.

27 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 28 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) & : }. Ha nem p(X) -et vesszük hozzá, akkor a kiírás kivételével ugyanaz. 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).

29 29 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 }. 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.

30 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 31 Felhasznált irodalom: SICStus Prolog User’s Manual


Letölteni ppt "SICStus Objects Objektum orientált kiterjesztés a SICStus Prolog nyelvhez Pereszlényi Attila Az előadás."

Hasonló előadás


Google Hirdetések