Mondjuk, hogy van egy geometriai formákkal dolgozó appunk. Van benne pont, háromszög (ami három pontból tevődik össze), kör (ami egy középpontból és egy sugárból), pl. így:
case class Pont(x: Int, y: Int)
case class Haromszog(p: Pont, q: Pont, r: Pont)
case class Kor(p: Pont, r: Double)
és szeretnénk valami olyan típust (pl. mert valami kollekcióba, listába, whatever, akarunk gyűjteni geometriai formákat (egyszerűség kedvéért most a pontot ne, csak köröket meg háromszögeket akarunk uniform módon kezelni) és ne kelljen ehhez két különböző típusú (mondjuk) tömböt deklaráljunk.
Vagyis: van egy T1 típusunk, aminek az értéktartománya a D1 halmaz, van egy T2 típusunk, aminek az értéktartománya pedig a D2 halmaz és ezekből szeretnénk készíteni egy olyan T típust, aminek az értéktartománya a D1⊎D2 halmaz, a két értéktartomány diszjunkt uniója. Ez azt jelenti, hogy még ha van is átfedés a két halmaz közt, akkor is minden elem "eredeti típus infóval" kerüljön bele, azaz ha van a két halmaznak közös eleme, akkor kétszer, egyszer T1 típusúként, egyszer pedig T2 típusúként. Pl. ha T1=Int és T2=Double, akkor a T típus értéktartományában szerepeljen a double 0 és az int 0 is külön-külön. Ha egy ilyen T típust hozunk létre ezzel az értéktartománnyal, akkor azt úgy mondjuk, hogy a T a T1 és T2 típusok összege, jelben T=T1+T2.
Most pont ezt szeretnénk: van egy Haromszog és egy Kor típusunk, és valami olyan típust szeretnénk készíteni, amibe bármelyiket rakhatjuk.
Ennek C-ben egy implementációja például így festhet:
vagyis: egy olyan structot készítünk, aminek a type mezője tárolja, hogy most épp kör vagy háromszög amire tulajdonképp mutatunk, és ennek függvényében van vagy egy Kor, vagy egy Haromszog adatmezőnk, de mivel egyszerre csak az egyik lehet valid, ezért őket unionba tesszük. Egy példa használata ennek az új típusnak:
Világos, hogy mi történik: amikor értéket adunk egy Shape változónak, akkor be kell állítsuk a típusát is és a union megfelelő mezőjét állítjuk az értékre; amikor meg dolgozunk egy Shape változóval, akkor legelőször is le kell switchelnünk, hogy épp mi is ez, és ezután típusfüggően dolgozhatunk vele. És létrehozhatunk egy Shape tömböt, amibe aztán pakolhatunk háromszögeket vagy köröket vegyesen ízlés szerint, ezzel megvalósítjuk az absztrakt Shape=Kor+Haromszog adattípust.
Scalában ugyenezt elérhetjük pl. így:
Ebből a match kifejezés egy külön poszt lesz, most a traitre fókuszálunk a típusdeklarációban. A Pont, Haromszog, Kor típusok definíciója ugyanaz, mint az előbb, azzal, hogy utóbbi kettő kapott egy extends Shape-et a végére és a definíciókat megelőzi egy trait Shape sor. Ez utóbbira egyelőre tekinthetünk úgy, mint egy típusdefinícióra: ha egy típust a trait kulcsszóval vezetünk be, akkor az még csak a nevét vezeti be a típusnak, egyelőre üres értéktartománnyal. Minden további típus, ami extendeli ezt a traitet, pedig hozzácsapja a saját értéktartományát a traitéhez, diszjunkt unió formában - mivel most két típusunk volt, aki azt mondta, hogy ő extends Shape, ezért most a Shape típus a Haromszog és a Kor típusok összege lesz. Láthatunk példát értékadásra is, a val shape:Shape = h értékdeklarálásnál azért írtam ki explicit a típust, mert különben a Scala fordító (mivel a h az egy háromszög) háromszögnek következteti ki a shape érték típusát.
A kód végén pedig azt láthatjuk, hogy ha van egy, a diszjunkt összegbe tartozó értékünk, akkor hogyan tudjuk meg róla azt, hogy éppen melyik típusnak az adattartományába valósi; a match kifejezésekről egy későbbi posztban többet fogunk tudni.
A trait egy ennél sokkal sokoldalúbb konstrukció lesz - most egyelőre csak az a lényeges tulajdonsága, hogy ezzel a kulcsszóval tudunk összeg típust létrehozni. Az összeg és szorzat típusok kombinációjával pedig tudunk építeni...
Vagyis: van egy T1 típusunk, aminek az értéktartománya a D1 halmaz, van egy T2 típusunk, aminek az értéktartománya pedig a D2 halmaz és ezekből szeretnénk készíteni egy olyan T típust, aminek az értéktartománya a D1⊎D2 halmaz, a két értéktartomány diszjunkt uniója. Ez azt jelenti, hogy még ha van is átfedés a két halmaz közt, akkor is minden elem "eredeti típus infóval" kerüljön bele, azaz ha van a két halmaznak közös eleme, akkor kétszer, egyszer T1 típusúként, egyszer pedig T2 típusúként. Pl. ha T1=Int és T2=Double, akkor a T típus értéktartományában szerepeljen a double 0 és az int 0 is külön-külön. Ha egy ilyen T típust hozunk létre ezzel az értéktartománnyal, akkor azt úgy mondjuk, hogy a T a T1 és T2 típusok összege, jelben T=T1+T2.
Most pont ezt szeretnénk: van egy Haromszog és egy Kor típusunk, és valami olyan típust szeretnénk készíteni, amibe bármelyiket rakhatjuk.
Ennek C-ben egy implementációja például így festhet:
typedef struct { int x; int y; } Pont;
typedef struct { Pont p; Pont q; Pont r; } Haromszog;
typedef struct { Pont p; double r; } Kor;
typedef struct {
int type; // 0 -- haromszog 1 -- kor
union{
Haromszog haromszog;
Kor kor;
};
} Shape;
vagyis: egy olyan structot készítünk, aminek a type mezője tárolja, hogy most épp kör vagy háromszög amire tulajdonképp mutatunk, és ennek függvényében van vagy egy Kor, vagy egy Haromszog adatmezőnk, de mivel egyszerre csak az egyik lehet valid, ezért őket unionba tesszük. Egy példa használata ennek az új típusnak:
Pont p; p.x = 1; p.y = 2;
Haromszog h; h.p = p; h.q = p; h.r = p;
Kor k; k.p = p; k.r = 1.0;
Shape shape;
shape.type = 0;
shape.haromszog = h;
printf( "Shape is: %s\n", shape.type ? "circle" : "triangle" );
switch( shape.type )
{
case 0:
printf( "Nodes: (%d,%d), (%d,%d), (%d,%d)\n",
shape.haromszog.p.x,
shape.haromszog.p.y,
shape.haromszog.q.x,
shape.haromszog.q.y,
shape.haromszog.r.x,
shape.haromszog.r.y
); break;
case 1:
printf( "Center: (%d,%d), radius: %lf\n",
shape.kor.p.x,
shape.kor.p.y,
shape.kor.r
);break;
}
Világos, hogy mi történik: amikor értéket adunk egy Shape változónak, akkor be kell állítsuk a típusát is és a union megfelelő mezőjét állítjuk az értékre; amikor meg dolgozunk egy Shape változóval, akkor legelőször is le kell switchelnünk, hogy épp mi is ez, és ezután típusfüggően dolgozhatunk vele. És létrehozhatunk egy Shape tömböt, amibe aztán pakolhatunk háromszögeket vagy köröket vegyesen ízlés szerint, ezzel megvalósítjuk az absztrakt Shape=Kor+Haromszog adattípust.
Scalában ugyenezt elérhetjük pl. így:
case class Pont(x: Int, y: Int)
trait Shape
case class Haromszog(p: Pont, q: Pont, r: Pont) extends Shape
case class Kor(p: Pont, r: Double) extends Shape
val p = Pont(1,2)
val h = Haromszog(p,p,p)
val k = Kor(p,1.0)
val shape: Shape = h
shape match {
case Haromszog(p,q,r) => println("Shape is: triangle\nNodes: " + p + "," + q + "," + r)
case Kor(p,r) => println("Shape is: circle\nCenter: " + p + ", radius: " + r)
}
Ebből a match kifejezés egy külön poszt lesz, most a traitre fókuszálunk a típusdeklarációban. A Pont, Haromszog, Kor típusok definíciója ugyanaz, mint az előbb, azzal, hogy utóbbi kettő kapott egy extends Shape-et a végére és a definíciókat megelőzi egy trait Shape sor. Ez utóbbira egyelőre tekinthetünk úgy, mint egy típusdefinícióra: ha egy típust a trait kulcsszóval vezetünk be, akkor az még csak a nevét vezeti be a típusnak, egyelőre üres értéktartománnyal. Minden további típus, ami extendeli ezt a traitet, pedig hozzácsapja a saját értéktartományát a traitéhez, diszjunkt unió formában - mivel most két típusunk volt, aki azt mondta, hogy ő extends Shape, ezért most a Shape típus a Haromszog és a Kor típusok összege lesz. Láthatunk példát értékadásra is, a val shape:Shape = h értékdeklarálásnál azért írtam ki explicit a típust, mert különben a Scala fordító (mivel a h az egy háromszög) háromszögnek következteti ki a shape érték típusát.
A kód végén pedig azt láthatjuk, hogy ha van egy, a diszjunkt összegbe tartozó értékünk, akkor hogyan tudjuk meg róla azt, hogy éppen melyik típusnak az adattartományába valósi; a match kifejezésekről egy későbbi posztban többet fogunk tudni.
A trait egy ennél sokkal sokoldalúbb konstrukció lesz - most egyelőre csak az a lényeges tulajdonsága, hogy ezzel a kulcsszóval tudunk összeg típust létrehozni. Az összeg és szorzat típusok kombinációjával pedig tudunk építeni...
folytköv
Harrah's Resort And Casino - Mapyro
ReplyDeleteWelcome to Harrah's Resort 안동 출장샵 And 전라남도 출장샵 Casino. 777 광주광역 출장안마 Harrahs Blvd, Henderson, NV 89101, US. Directions. (775) 622-5000. Directions · (775) 강원도 출장샵 622-5000. Call Now · More Info. Hours, Accepts Credit Cards, Attire, Wi-Fi Rating: 4.1 · 8,951 votes 포천 출장마사지