A Blue programozási nyelv

Típusok, típuskonstrukciók

Változók és kifejezések

Bármely osztályhoz definiálhatunk változókat. Ezt az osztályokon belül külön részekben tehetjük meg. Ilyen szekció létezik az egész osztály számára (példányváltozók) és minden egyes rutinban (lokális változók). A szekciókat a var kulcsszó vezeti be. A példányváltozók hatásköre az osztálydefiníció. A lokális változóké a rutin, amiben deklarálásra kerültek.


Példa:
var num1, num2: Integer count: Integer := 0 printList(l:List) is == kiirja a lista elemeit var cnt: Integer nm:String:="" do ... end printList

A lokális változók élettartama a rutin futásának idejével egyezik meg (hasonlóan a Pascal-hoz). Nem lehetséges a lokális változó élettartalmát a rutin futása utánra is kiterjeszteni (mint például a static kulcsszóval C-ben). Egy példányváltozó élettartama megegyezik az őt tartalmazó objektum létezésének idejével.

A változók a típus, az állapot és az érték egy kombinációi. A változó típusa statikusan meghatározott és soha nem változik meg. Egy változónak két állapota lehet: definiált vagy nemdefiniált. Ha egy változó definiált, akkor értéke is van. Egy változó értéke mindig a típusának megfelelő objektumra mutató referencia (vagy nil, amely egy speciális érték, és azt jelenti, hogy a változó egyetlen objektumra sem hivatkozik).

A változók deklarációkor bármilyen megengedett kifejezéssel inicializálhatók, felhasználva az értékadó utasítást. Ha egy változót nem inicializálunk a deklarációjakor, akkor kezdeti állapota nemdefiniált. Nemdefiniált állapotú változó használata nem megengedett, futásidejű hibát eredményez.

A nyelvben nem létezik függvény a nemdefiniált állapot ellenőrzésére. A programozó felelőssége a programírás folyamán biztosítani, hogy a ne legyen nemdefiniált állapotú változó használva. (Egy jó programozó mindig tudja, hogy mikor lehet egy változó nemdefiniált. A paraméterek sosem lehetnek nemdefiniáltak, hiszen az már a hívás idejében futásidejű hibához vezetne.)

Az értékadó utasítás hatására az értékadás bal oldalán álló változó állapota definiáltra változik. Egy definiált változó később sohasem lehet nemdefiniált.

A változók nem jelennek meg az osztály interface-ében, elrejtve maradnak a külvilágtól (encapsulation). Más osztály direkt módon nem férhet hozzá az osztály változóihoz. (Közvetett módon még hozzáférhet, ha az osztály rendelkezik egy függvénnyel, ami visszaadja vagy megváltoztatja a változó értékét, de ez a változót tartalmazó osztály "döntése".)

Közvetlenül hozzáférhető változók csak az aktuális rutin lokális változói, és az aktuális osztály példányváltozói.

Fontos megjegyezni, hogy az enkapszuláció osztály és nem objektum alapú. Ez azt eredményezi, hogy egy osztály hozzá tud férni egy másik objektum változóihoz, ha az az objektum ugyanahhoz az osztályhoz tartozik.


Példa:
class Point is ... var x,y: Integer ... add (other : Point) is == mas objektum pontjait rendeljuk hozza ehhez do x:=other.x y:=other.y end add

Ez a technika jól használható akkor, ha szükség van a belső részekhez való hozzáférésre, de nincs az interface-ben hozzáférési rutin definiálva. (Egy objektum klónozására szolgáló függvény, amikor egy objektum létre akar hozni egy, a saját osztályába tartozó új objektumot a sajátjáéval megegyező adattagokkal, például egy ilyen eset. Nem lenne célszerű minden változóhoz kívülről hozzáférést biztosítani csak a klónozás kedvéért.)

A lehetőség, hogy más objektum példányváltozóihoz hozzáférjünk - még akkor is, ha ugyanazon az osztályhoz tartoznak - némelyek számára ellentmondásos az információelrejtés (vagy enkapszuláció) elvével. Bizonyos szemszögből ez így is van. Ahhoz, hogy megértsük miért érdemes mégis ezt a hozzáférést megengedni, először meg kell értenünk, hogy mire jó az információelrejtés.

Az információelrejtés egy szoftvertervezési technika, amely elválasztja különböző modulok (itt: osztályok) implementációját egymástól. A tetszőleges helyen történő közvetlen változóhozzáférés megengedése katasztrofális a karbantarthatóságra nézve, hiszen egyetlen modul implementációjának megváltoztatása sok más helyen történő váratlan változtatást tehet szükségesség a programban. Ez az oka annak, hogy nem engedjük a példányváltozók közvetlen elérését.

Ha viszont minden hozzáférés ugyanabból az osztályból ered, akkor (még ha másik objektumból is történik) a fenti érvelés nem érvényes többé. Ha megváltoztatjuk az implementációját annak az osztálynak, minden hozzáférést is megváltoztatunk az adott változóhoz az osztályon belül. Ezért a példányváltozókhoz történő hozzáférés megengedése más - azonos osztályból származó - objektumok számára nem jelent problémát.

Konstansok

A konstansok a Blue-ban vagy literálok, vagy névvel ellátott konstansok.

Literálok

Literálok léteznek az előre definiált osztályokhoz.


Példa literálokra:
Integer: 17 0 -5 Real: 2.0 0.0 -0.122 Boolean: true false TRUE String: "hello" "" "ab\n"

Névvel ellátott konstansok

Névvel ellátott konstansok minden megengedett kifejezésből képezhetők. A névvel ellátott konstansokat egy különálló részben definiálhatjuk, amit a const kulcsszó vezet be. Minden változódeklarációs részt megelőzhet egy konstansdeklarációs rész. A hatáskörre vonatkozó szabályok megegyeznek a változókra vonatkozókkal, és a deklaráció szintaxisa is azonos, kivéve hogy az inicializálás kötelező.


Példa névvel ellátott konstansokra:
const size: Integer := 99 default_title: String := "untitled"

A konstansok inicializálása során literálok, valamint tetszőleges függvényhívás is használható. Példányváltozók nem használhatók példánykonstansok inicializálásra - még nem inicializáltak. A függvényhívásokra különös figyelmet kell fordítani: ha az inicializálásra használt függvény példányváltozókat használ, futás idejű hiba keletkezik nem inicializált változó használata miatt. A példányváltozók és példánykonstansok inicializálása még az objektum konstruktorának meghívása előtt történik.

Az objektum inicializálásának pontos rendje:

Minden konstans és változó a deklaráció sorrendjében inicializálódik. Egy későbbi definíció használhatja a megelőzőket.

Halmazkonstansok

Lehetőség van literál halmazok létrehozására. Ilyen típussal rendelkező változót nem lehet létrehozni, és az egyetlen műveletük az in, amely a halmazba tartozást teszteli és boolean értékkel tér vissza. A case utasításban is halmazkonstansok használatosak.


Példa:
if choice in {1, 2, 3 } then ... if result in {0..9} then ... whitespace := ch in {" ", "\n", "\t"} if ch in {"a".."z", "A".."Z", "_"} then ...

Ahogyan az a példákból is látszik, halmazokat értékek vagy intervallumok vesszővel elválasztott listájaként lehet létrehozni.

Intervallumok csak Integer, String és Enumeration típusok részintervallumai lehetnek.

Ez a konstrukció nem helyettesít egy általános célú halmaztípust. Pusztán egy jelölés, amely kényelmesebbé teszi az összehasonlító (<=, stb.) műveletek használatát. Egy általános célú halmaztípus megtalálható a Blue Standard Collection Library-ben.