Język Smalltalk
|
Opis języka Smalltalk jest tworzony na bieżąco. Jeżeli możesz podzielić się swoja wiedzą na temat języka Smalltalk, to .
|
Składnia
Konwencje nazewnictwa
Nazwy klas, zmiennych, metod i innych elementów są w Smalltalku na ogół dłuższe niż w większości innych języków, głównie ze względu na filozofię języka, zakładającą możliwie duże zbliżenie do języka naturalnego i możliwość zrozumienia algorytmu przez osobe nie znającą Smalltalka.
Nazwy składają się z reguły z dwóch lub więcej słów, przy czym drugie i kolejne słowa zaczynają się z dużej litery, np. loopCounter, upperMirrorRegion.
Stosowanie tej konwencji jest dobrowolne i nie jest w żaden sposób wymuszane przez sam język, przyjęte jest jednak powszechnie w świecie smalltalkowym, ponieważ zwiększa znacznie czytelność kodu.
Z małej czy z dużej litery?
| Rodzaj nazwy |
Z dużej litery? |
Przykład |
| Kategoria klas |
tak (zalecane) |
Magnitude-General |
| Klasa |
tak (wymagane) |
Date |
| Zmienna klasowa |
tak (wymagane) |
MonthNames |
| Zmienna globalna |
tak (wymagane) |
MaximumUsers |
| Zmienna pool |
nie (zalecane) |
cr |
| Zmienna instancyjna |
nie (zalecane) |
year |
| Zmienna tymczasowa |
nie (zalecane) |
aDate |
| Kategoria metod |
nie (zalecane) |
accessing |
| Metoda |
nie (zalecane) |
monthName |
Literały
Smalltalk posiada sześć typów literałów:
- liczby
- znaki
- ciagi znaków
- symbole
- tablice bajtów
- tablice literalów
Dodatkowo istnieją trzy specjalne literały: nil, true i false.
Stała logiczna true jest jedyną instancją klasy True, która jest podklasą klasy Boolean.
Stała logiczna false jest z kolei jedyną instancją klasy False, która również jest podklasą klasy Boolean.
Objekt nil jest jedyną instancją klasy UndefinedObject. Jak sama nazwa sugeruje nil jest wartością nadawaną zmiennej nie przechowującej żadnej bardziej interesującej wartości. Przykładowo każda zmienna w Smalltalku jest po jej deklaracji niejawnie inicjowana wartością nil.
Przykład:
| value | "Deklaracja zmiennej"
Transcript
cr;
show: value printString. "Wartością zmiennej value jest nil"
value := 1.
Transcript
cr;
show: value printString. "Wartością zmiennej value jest 1"
|
Jeżeli nie wiesz co to jest Transcript, kliknij tutaj.
Efektem wykonania powyższego skryptu będzie:
'UndefinedObject'
'1'
Zmienne
W Smalltalku istnieje sześć typów zmiennych:
- zmienne tymczasowe,
- zmienne instancyjne,
- klasowe zmienne instancyjne,
- zmienne klasowe,
- zmienne pool,
- zmienne globalne
oraz dodatkowo trzy zmienne specjalne: self, super i nil.
Zmienne tymczasowe i instancyjne są są zmiennymi prywatnymi, ponieważ ich zasięg jest ograniczony do odpowiednio metody i instancji. Z kolei zmienne klasowe, instancyjne zmienne klasowe, zmienne pool i globalne są dostępne z dowolnego miejsca.
Domyślną wartością każdej nowoutworzonej zmiennej jest nil. Przypisanie do zmiennej nowej wartości następuje za pomocą operatora przypisania ":=":
Można również w jednym wyrażeniu przypisać taką samą wartość do więcej niż jednej zmiennej:
Można tak jednak przypisywać wyłącznie wartości "tylko do odczytu" lub literały, w przeciwnym wypadku zmiana jednej zmiennej powoduje skutek uboczny w postaci zmiany wartości drugiej zmiennej.
Zmienne specjalne
W Smalltalku istnieją trzy specjalne zmienne do których nie można przypisać żadnej wartości: self, super i thisContext. Wartości zwracane przez te zmienne są zależne od kontekstu ich wykonania.
Zmienna self wskazuje na obiekt, który wykonuje aktualną metodę. W najprostszym wypadku zmienna self pozwala z wnętrza jednej metody danego obiektu wywołać inną metodę należącą do tego samego obiektu. Na przykład metoda bounds instancji klasy Rectangle może użyć metody computeBounds z tego samego obiektu za pomocą wyrażenia self computeBounds.
Zmienna super różni się od self tym, że poszukiwanie implementacji metody, która ma być wywołana rozpoczyna się w nadklasie klasy, której instancją jest dany obiekt. Jeżeli nadklasa nie implementuje danej metody wywołana zostanie metoda z obiektu, który wywołal super. Na przykład wywołanie super bounds wewnątrz metody instancji klasy Rectangle spowoduje, że zostanie wywołana metoda bounds zdefiniowana w klasie Geometric. Natomiast wywołanie super rounded spowoduje wywołanie metody rounded zdefiniowanej w klasie Rectangle, ponieważ klasa Geometric nie implementuje tej metody.
Drugą różnicą w stosunku do self jest to, że zmienna super nie może zostać przypisana do żadnej innej zmiennej.
Przykład:
| value |
value := self. "Poprawne."
value := super. "Tak nie można!"
|
Zmienne niezadeklarowane
Jeżeli jakaś zmienna zostanie usunięta z systemu ale istnieją do niej ciągle referencje, to jej nazwa jest automatycznie wstawiana do katalogu ze zmiennymi niezadeklarowanymi (Undeclared). Katalog ten jest zarządzany automatycznie przez system.
Wiadomości
Wiadomość w Smalltalku składa się z nazwy metody i argumentów i jest wysyłana do odbiorcy wiadomości. W wyrażeniu 9 raisedTo: 2 odbiorcą wiadomości jest liczba 9, nazwą metody jest raisedTo:, a argumentem jest liczba 2.
Każda wiadomość zwraca jako rezultat swojego wykonania jakiś obiekt do obiektu wysyłającego daną wiadomość. W powyższym przykładzie metoda raisedTo: zwraca instancję klasy SmallInteger, czyli liczbę 81. Domyślnie każda metoda zwraca odbiorcę wiadomości (self). Stosując operator "^" można zwrócić dowolny inny obiekt:
^6 "Zwraca liczbę 6"
^7 + 2 "Zwraca liczbę 9"
|
Istnieją trzy rodzaje wiadomości: unarna (ang. unary), binarna (ang. binary) i wiadomość wieloargumentowa, składająca się z jednego lub kilku słów kluczowych (ang. keyword).
Wiadomości unarne
Wiadomość unarna posiada nazwę metody, ale nie ma argumentów.
Przykłady:
1.0 sin "Zwraca sinus z liczby 1.0"
Array new. "Zwraca pustą tablicę"
Date today. "Zwraca aktualną datę"
|
Wiadomości binarne
Wiadomość binarna używa znaku specjalnego, na przykład znaku "+", jako nazwy metody i posiada dokładnie jeden argument. Niektóre wiadomości binarne składają się z kombinacji dwóch znaków specjalnych, na przykład operator porównania ">=".
Metody binarne w Smalltalku:
| Nazwa metody |
Przykład |
Opis |
+ |
1 + 2 |
Operator dodawania |
- |
12 - 3 |
Operator odejmowania |
* |
3 * 2 |
Operator mnożenia |
/ |
9 / 3 |
Operator dzielenia |
** |
2 ** 3 |
Potęgowanie |
// |
17 // -2 |
Dzielenie całkowite (bez reszty) |
\\ |
17 \\ -2 |
Reszta z dzielenia |
< |
index < 100 |
Mniejszy niż |
<= |
index <= 10 |
Mniejszy lub równy |
> |
index > 1 |
Większy niż |
>= |
index >= 10 |
Większy lub równy |
= |
index = 7 |
Wartości są równe |
~= |
index ~= 6 |
Wartości nie są równe |
== |
x == y |
Ten sam obiekt (odbiorca i argument są tym samym obiektem lub wskazują na ten sam obiekt) |
~~ |
x ~~ y |
Różne obiekty |
& |
(a < 0) & (b = 1) |
Logiczny AND |
| |
(a < 0) | (b = 1) |
Logiczny OR |
, |
'abc','def' |
Łączenie dwóch ciagów znaków |
@ |
2 @ 3 |
Zwraca instancję klasy Point (x jest odbiorcą wiadomości, a y jest jej argumentem) |
-> |
#columns -> 3 |
Zwraca instancję klasy Association (klucz jest odbiorcą wiadomości, a wartość jest jej argumentem) |
Wiadomości wieloargumentowe
Wiadomości wieloargumentowe składają się z jednego lub więcej słów kluczowych, zakończonych dwukropkiem po którym następuje argument metody.
Przykłady:
Array new: 5. "Tworzy tablicę pięcioelementową"
Rectangle left: 2 top: 4 right: 10 bottom: 12. "Tworzy kwadrat"
'abcdefgh' copyFrom: 2 to: 5. "Kopiuje elementy od 2 do 5 do nowej instancji klasy String"
|
Kolejność wykonywania wiadomości
Kolejność wykonywania wiadomości w wyrażeniach jest w Smalltalku następująca:
- Wyrażenia ujęte w nawiasy przed wyrażeniami poza nawiasami.
- Wiadomości unarne przed wiadomosciami binarnymi.
- Wiadomości binarne przed wiadomosciami wieloargumentowymi.
Wszystkie wyrażenia w Smalltalku są wykonywane od lewej strony wyrażenia do prawej, również wyrażenia zawierające operatory matematyczne, które w Smalltalku są normalnymi metodami. Tak więc przykładowo wynikiem wyrażenia "x := 3 + 2 * 6." będzie liczba 30, a nie 15 jak wynikałoby z reguł matematycznych.
Jeżeli kilka kolejnych wiadomości jest wysyłanych do tego samego obiektu, to wiadomości te mogą zostać kaskadowane, przy użyciu średnika.
Tak więc zamiast pisać:
anObject doSomething.
anObject doSomething1.
anObject doSomething2.
|
Można prościej napisać:
anObject
doSomething;
doSomething1;
doSomething2.
|
|