Pharo

Bazirano na Pharo MOOC

Prof. dr Igor Dejanović (igord at uns ac rs)

Kreirano 2023-01-16 Mon 18:16, pritisni ESC za mapu, m za meni, Ctrl+Shift+F za pretragu

1. Smalltalk

1.1. Šta je Smalltalk?

  • Objektno-orijentisani dinamički reflektivni jezik.
  • Xerox PARC - Alan Kay, Dan Ingalls i drugi - tokom 70-ih.
  • Uticao na razvoj Actor model obrasca.
  • Nastao pod uticajem Simule (prvi OO jezik, Norwegian Computing Center u Oslu - 60-te).
  • Jedan od najuticajnijih jezika.
  • Napredni koncepti: sve je objekat, razmena poruka, “živ” sistem, virtualna mašina.
  • Konstrukcionistički pristup programiranju.

1.2. Istorijat

  • Razvijen u par dana 1971 godine (Smalltalk-71) zbog opklade (Alan Kay).
  • Kasnija verzija Smalltalk-72 je korišćena u istraživanjima.
  • Smalltalk-76 - nasleđivanje klasa, razvojno okruženje
  • Najpoznatija verzija Smalltalk-80 - meta-klase. Prva verzija dostupna van PARC-a (Apple, HP, DEC, UC Berkeley)
  • Standardizovan - ANSI 1998

1.3. Smalltalk implementacije

  • Komercijalne
    • Smalltalk-80 (Xerox PARC)
    • VisualWorks (ParcPlace Systems, prodato 1999 firmi Cincom)
    • IBM VisualAge - napušteno u korist Jave. Današnji Eclipse je započeo kao VisualAge Smalltalk okruženje. Jedno vreme je i Java podrška bila implementirana u Smalltalk-u.
  • FLOSS:
    • Squeak (moderna verzija Smalltalk-80) - Apple -> Disney -> HP Labs -> SAP Labs -> Y Combinator
    • Pharo - fork Squeak-a (2008) sa ciljem upotrebe u istraživanju i komercijalnim projektima (Pharo consortium, Pharo association)
    • Amber Smalltalk - Smalltalk u JavaScrript-u

1.4. Familija Smalltalk i vezanih jezika

smalltalk-history.png

2. Pharo uvod

2.1. Pharo

  • Pravi OO jezik (“sve je objekat”) + IDE!
  • Inspirisan Smalltalk-om
  • Aktivna zajednica
  • “Živ” sistem.
  • Jednostavan i moćan objektni model
  • Radi na Mac OSX, Linux, iOS, Android, Windows, Pi.
  • 100% MIT
  • Pregled nekih osobina Pharo IDE i jezika

2.2. Pharo instalacija

  • Preporučena upotreba Pharo Launcher alata
    • Instalacija i upravljanje slikama i virtualnim mašinama
  • Alternativno, može se koristiti Zeroconf skripta:
# 64bit version
mkdir pharo
cd pharo
curl -L https://get.pharo.org/64/ | bash
# or if curl is not available:
wget -O- https://get.pharo.org/64 | bash
# 32bit version
curl -L https://get.pharo.org | bash
# or if curl is not available:
wget -O- https://get.pharo.org | bash

2.3. Pharo fajl komponente

pharo
Pharo8.0-32bit-a153e04
Pharo.changes
Pharo.image
pharo-ui
pharo-vm
  • pharo-vm - Pharo virtuelna mašina (OS-specific)
  • Pharo.image - Perzistirano stanje/objekti
  • Pharo...sources - Izvorni kod izdanja
  • Pharo.changes - Promene u izvornom kodu od početka upotrebe
  • Pharo.image i Pharo.changes su fajlovi gde dolazi do promena
  • Pharo.changes se menja kada menjamo kod
  • Pharo.image se menja kada eksplicitno tražimo perzistenciju stanja

2.4. Cela sintaksa

Staje na jedan slajd:

exampleWithNumber: x
    "A method that illustrates every part of Smalltalk method syntax."
    <menu>
    | y |
    true & false not & (nil isNil) ifFalse: [self halt].
    y := self size + super size.
    #($a #a "a" 1 1.0)
        do: [ :each |
            Transcript show: (each class name);
                       show: (each printString);
                       show: ' '].
    ^x < y

2.5. Model

  • Dinamički tipiziran
  • Sve je objekat tj. instanca klase
  • Sve metode su javne i virtualne
  • Svi atributi su zaštićeni
  • Jednostruko nasleđivanje (Single inheritance)

2.6. Napisan u samom sebi

  • Sve je napisano u Pharo!
  • Jednostavna sintaksa/model za pristup svemu.

    hands.jpg

2.7. Introspekcija

  • Pharo nije “crna kutija”.
  • Sve što vidite su objekti sa kojima možete stupiti u interakciju i menjati ih “naživo”.
  • Program koji se razvija je nerazdvojni deo razvojnog okruženja.
  • Npr. Alt+Shift+Click -> Halo hendleri!

halo.png

2.8. Samo objekti, poruke…

  • Objekti: mouse pointer, booleans, arrays, numbers, strings, windows, files, sound, url, socket, font, text, streams…
  • Poruke (messages): size, +, at:put:, do:, collect:, ifTrue:ifFalse:
  • Poruke predstavljaju nameru (šta treba uraditi). Metode opisuju kako treba nešto uraditi.
  • Objekat koji prima poruku zovemo prijemnikom (receiver).

2.9. … i blokovi (Block Closures)

  • Blokovi su vrsta anonimnih metoda.
4 timesRepeat:
    [ Transcript show: 'Hello World!']
  • Blokovi se navode unutar [].

2.10. Jednostavan, elegantan i uniforman model

  • Sve je objekat tj. instanca klase.
    • Klase i poruke su takođe objekti.
  • Svo procesiranje se obavlja razmenom poruka (message passing) između objekata.
  • Koristimo izraz slanje poruke jer:
    • metode se određuju dinamički
    • kasno povezivanje (late binding), samo virtuelni pozivi
  • Postoji samo jedan mehanizam za pretragu metoda za sve objekte.

2.11. Pharo objektni model

  • Atributi instanci (instance variables) su zaštićeni (protected):
    • Privatni za objekat
    • Dostupni podklasama
  • Metode su javne (public) i virtualne.
  • Jednostruko nasleđivanje klasa.

2.12. Slanje poruka

Date today

Date today + 3 days

2 + 3

(point1 x * point2 y) - (point1 y * point2 x)

2.13. Kreiranje objekata

Obavlja se slanjem poruke drugom objektu

10@20

Nova instanca klase Point se kreira:

  • slanjem poruke @
  • objektu 10 (SmallInteger)
  • sa argumentom 20 (SmallInteger)

2.14. Kreiranje objekata - String

'Pharo', 'is cool!'
=> 'Pharo is cool!'

Novi string se kreira spajanjem dva stringa tako što:

  • se šalje poruka ,
  • stringu 'Pharo'
  • sa parametrom 'is cool!'

2.15. Kreiranje objekata

Slanjem poruke new ili new: klasi

Monster new
=> aMonster

U prethodnom primeru Monster je ime klase a new je poruka koja se šalje ovoj klasi. Rezultat je nova instanca klase Monster.

Kreiranje niza dužine 6.

Array new: 6
=> #(nil nil nil nil nil nil)

Slanjem poruke klasi izvršava se metoda klase (class method).

Tamagoshi withHunger: 10

2.16. Less is more!

  • Bez konstruktora
  • Bez statičkih metoda
  • Bez deklaracije tipova
  • Bez interfejsa
  • Bez package/private/protected modifikatora
  • Bez parametrizovanih tipova
  • Bez boxing-a
  • Ali i dalje vrlo moćan jezik!

2.17. Hello world

'Hello World' asMorph openInWindow

Šaljemo poruku asMorph stringu Hello World i dobijamo grafički element (Morph). Dobijenom grafičkom elementu šaljemo poruku openInWindow da bi ga prikazali u prozoru.

2.18. Primer - preuzimanje slike sa web-a

(ZnEasy getPng: 'http://pharo.org/web/files/pharo.png') asMorph openInWindow
  • ZnEasy je ime klase. Klase su globalno dostupe i nazivi počinju sa velikim slovom.
  • getPng: je poruka koju šaljemo klasi ZnEasy. Ova poruka ima argument. U ovom slučaju to je string 'http://pharo.org/web/files/pharo.png'
    • Poruke koje imaju argumente se pišu sa : na kraju naziva i mogu biti višesložne. Ovakve poruke nazivamo keyword message.
  • Poruka asMorph šalje se objektu koji vraća poruka getPng:. Ovo je obična unarna poruka bez argumenata.
  • Poruka openInWindow se šalje objektu koji vraća poruka asMorph.
  • Ove dve unarne poruke se primenjuju s leva na desno.

2.19. Sintaksni elementi jezika

Vrsta Primer
Komentar "Ovo je komentar"
Karakteri $c $# $@
String 'Ovo je string'
Simbol (jedinstveni string) #prvi #+
Literal niz #(23 56 89)
Integer 45, 2r10100
Real 1.5, 6.03e-34, 4, 2.4e7

2.20. Sintaksni elementi jezika

Vrsta Primer
Boolean true, false
  (instanca True i False)
Undefined nil (instanca UndefinedObject )
Point 10@120

2.21. Osnovne jezičke konstrukcije

  • Deklaracija privremene varijable: | var |
  • Dodela vrednosti varijabli: var := aValue
  • Separator iskaza: obj1 message1. obj2 message2.
  • Povratak vrednosti iz metode: ^ aValue
  • Blokovi (leksička zatvorenja ili anonimne metode)
[ :x | x + 2 ] value: 5
=> 7

3. Poruke

3.1. Tri vrste poruka

  1. Unarne poruke:

    • Sintaksa: receiver selector
    • Primeri:
       9 squared
       Date today
    
  2. Binarne poruke:

    • Sintaksa: receiver selector argument
    • Primeri:
       2 + 3
       3 @ 4
    
  3. Keyword poruke:

    • Sintaksa: receiver key1: arg1 key2: arg2
    • Primeri:
       2 between: 10 and: 20
       5 to: 10 do: [ :i | Transcript show: i ]
    

3.2. Slanje unarne poruke

receiver selector

Primer:

10000 factorial

Šaljemo poruku factorial objektu 10000.

3.3. Slanje binarne poruke

receiver selector argument

Primer:

1 + 3

Šaljemo poruku + objektu 1 sa parametrom 3.

3.4. Slanje keyword poruke

receiver keyword1: arg1 keyword2: arg2

Ekvivalentno u Javi ili C-like jezicima:

receiver.keyword1keyword2(arg1, arg2)

3.5. Keyword poruke za Java programere

U Javi

postman.send(mail, recipient);
postman . send ( mail , recipient );
postman send mail recipient
postman send mail to recipient

U Pharo/Smalltalk-u

postman send: mail to: recipient

3.6. Primer: slanje HTTP zahteva

ZnClient new
  url: 'https://en.wikipedia.org/w/index.php';
  queryAt:'title' put:'Pharo';
  queryAt:'action' put:'edit';
  get
  • new je unarna poruka koja se šalje klasi ZnClient
  • queryAt:put: je keyword poruka sa dva argumenta
  • get je unarna poruka
  • ; je specijalan operator koji zovemo kaskada (cascade) - šaljemo poruku istom objektu primaocu.

3.7. Poruke su svuda

  • Uslovi
  • Petlje
  • Iteracije
  • Konkurencija

3.8. Primer - Integer>>factorial

factorial
	"Answer the factorial of the receiver."

	self = 0 ifTrue: [^ 1].
	self > 0 ifTrue: [^ self * (self - 1) factorial].
	self error: 'Not valid for negative integers'
  • ifTrue: je poruka koja se šalje Boolean objektu koji vraća poruka = poslata objektu self sa parametrom 0.
  • Postoje i ifTrue:ifFalse:, ifFalse:ifTrue: i ifFalse:
  • Implementirane su u klasama True i False i možete ih pročitati. Ne postoji ništa specijalno u vezi ovih poruka!

3.9. Kompozicija poruka - s leva na desno

Šta se dešava kada imamo sukcesivne poruke istog tipa?

1000 factorial class name
> 'LargePositiveInteger'

ekvivalentno je sa:

(((1000 factorial) class) name)

3.10. Prioriteti poruka

(Msg) > Unary > Binary > Keywords

Ova pravila redukuju potrebu za navođenjem zagrada.

3.11. Prioritet primeri

2 + 3 squared
> 2 + 9
> 11
  • Prvo unarna squared
  • Zatim binarna +

3.12. Prioritet primeri

2 raisedTo: 3 + 2
> 2 raisedTo: 5
> 32
  • Prvo binarna +
  • Zatim keyword raisedTo:

3.13. Prioritet primeri

Color gray - Color white = Color black
> aGray - aWhite = aBlack
> aBlack = aBlack
> true
  • Prvo unarne
  • Zatim binarne s leva na desno: - pa onda =

3.14. Prioritet primeri

1 class maxVal + 1
> 1073741824
  • unarna class, unarna maxVal, binarna +
1 class
> SmallInteger

1 class maxVal
> 1073741823

1 class maxVal + 1
> 1073741824

(1 class maxVal + 1) class
> LargePositiveInteger

3.15. Upotreba zagrada kod prioriteta

0@0 extent: 100@100 bottomRight
> Message not understood
> 100 does not understand bottomRight

Moramo koristiti zagrade:

(0@0 extent: 100@100) bottomRight
> (aPoint extent: anotherPoint) bottomRight
> aRectangle bottomRight
> 100@100

3.16. Cena jednostavnosti/uniformnosti

Samo poruke:

  • +
    • je poruka (nije operacija), ne postoji specijalno definisani prioritet
    • možemo je redefinisati za različite domene
  • Jednostavnost
  • Ograničenje: nemamo definisan matematički prioritet operacija

3.17. Nema prioriteta aritmetičkih operacija

3 + 2 * 10
> 5 * 10
> 50

Moramo pisati sa zagradama:

3 + (2 * 10)
> 3 + 20
> 23

3.18. Nema prioriteta aritmetičkih operacija

1/3 + 2/3
> 7/3 /3
> 7/9

Moramo pisati:

(1/3) + (2/3)
>1

3.19. Sekvenca izraza

. je separator:

expression1.
expression2.
expression3

Primer:

Transcript cr.
Transcript show: 1.
Transcript show: 2

3.20. Sekvenca izraza

  • . je separator a ne terminacija.
  • Nema potrebe da se stavlja na kraju niza izraza.
  • Ne stavlja se posle deklaracije privremenih promenjivih.
| macNode pcNode |
macNode := Workstation withName: #mac.
macNode sendPacket: 'Hello World'

3.21. Slanje više poruka istom objektu - kaskada (;)

|c|
c := OrderedCollection new.
c add: 1.
c add: 2

Ekvivalentno je sa:

OrderedCollection new
   add: 1;
   add: 2
  • add: 2 se šalje istom prijemniku poruke add: 1 a to je objekat vraćen porukom new.

4. Blokovi

4.1. Blokovi izgledaju kao funkcije

fct(x) = x*x + 3

fct := [ :x | x * x + 3 ]

fct(2)

fct value: 2

4.2. Blokovi

  • Anonimne metode
[ :each | Transcript show: each abs printString; cr ]
  • Leksička “zatvorenja” (closures)
  • Takođe su objekti:
    • Mogu se proslediti kao argumenti poruka
    • Mogu se dodeliti varijablama
    • Mogu biti povratne vrednosti metoda

4.3. Upotreba blokova

#(1 2 -4 -86) do: [ :each | Transcript show: each abs printString; cr ]
> 1
> 2
> 4
> 86
  • Pišu se unutar []
  • Mogu imati parametre - navode se kao simboli pre | (:each)
  • U ovom primeru blok se evaluira za svaki element niza. :each dobija redom vrednosti niza.
  • value: poruka se koristi za evaluaciju bloka.

4.4. Definicija bloka ne izvršava kod

(1/0)
-> Greška

Ali nema greške pri definiciji bloka:

  • Definicija bloka ne izvršava kod
  • Definicija bloka “zamrzava” izračunavanje definisano telom bloka.
[1/0]
> [1/0]

[1/0].
1 + 2
> 3

4.5. Izvršavanje blokova

Obavlja se eksplicitno slanjem poruke value.

[2 + 6] value
> 8

[1/0] value
> Error

4.6. Blok sa jednim argumentom

Blokovi mogu imati argumente (kao i metode):

[ :x | x + 2 ]
  • :x predstavlja argument bloka
  • x + 2 je telo bloka
[ :x | x + 2 ] value: 5
> 7
  • Poruka value: izvršava blok sa parametrom 5.
    • x dobija vrednost 5 za vreme izvršavanja bloka.

4.7. Vrednost evaluacije bloka

Evaluacija bloka vraća vrednost poslednjeg izraza u bloku:

[:x|
 x + 33.
 x + 2] value: 5
> 7

4.8. Blokovi se mogu sačuvati

  • Blok se može sačuvati kao vrednost varijable
  • Blok se može evaluirati više puta
| add2 |
add2 := [ :x | x + 2 ].
add2 value: 5.
>7

add2 value: 33
> 35

4.9. Blokovi mogu imati više argumenata

Primer:

[ :x :y | x + y ]

:x :y su argumenti bloka.

Kako se izvršava blok sa dva argumenta?

[ :x :y | x + y ] ??? 5 7
> 12
[ :x :y | x + y ] value: 5 value: 7
> 12
  • value:value: je poruka sa dva argumenta koja se šalje bloku sa parametrima 5 i 7

4.10. Blokovi sa privremenim varijablama

Blokovi mogu definisati lokalne privremene varijable (kao i metode):

Collection>>affect: anObject when: aBoolean
  self do: [ :index | | args |
            args := ....
            aBoolean
            ifTrue: [ anObject do: args ]
            ifFalse: [ anObject doDifferently: args ] ].

  • | args | definiše privremenu varijablu args
  • args postoji samo za vreme izvršavanja bloka

4.11. Povratak iz bloka izaziva povratak iz metode

Kada se ^ izvrši unutar bloka dolazi do povratka iz metode u kojoj je blok definisan:

Integer>>factorial
  "Answer the factorial of the receiver."

  self = 0 ifTrue: [ ^ 1 ].
  self > 0 ifTrue: [ ^ self * (self − 1) factorial ].
  self error: 'Not valid for negative integers'
0 factorial
>1

42 factorial
>1405006117752879898543142606244511569936384000000000

4.12. Dizajn saveti za upotrebu blokova

  • Koristi blokove sa najviše 2 ili 3 parametra
  • Definisati klasu umesto bloka za više parametara

5. Petlje i iteracije

5.1. Petlje su takođe implementirane kao poruke

1 to: 4 do: [ :i | Transcript << i ]
> 1
> 2
> 3
> 4
  • to:do: je poruka poslata broju (instanci Integer klase)

5.2. Petlje su takođe implementirane kao poruke

  • Mnoge druge vrste petlji: timesRepeat:, to:by:do:, whileTrue:, whileFalse:
4 timesRepeat: [self doSomething ]

0 to: 100 by: 3 do: [ :i | ... ]
  • Možete lako napraviti novu vrstu petlje koja se neće razlikovati od sistemske.

5.3. whileTrue:

[ ... ] whileTrue: [ ... ]

Izvršava argument dok god je vrednost prijemnika true

Color >> atLeastAsLuminentAs: aFloat
  | revisedColor |
  revisedColor := self.
  [ revisedColor luminance < aFloat ]
    whileTrue: [ revisedColor := revisedColor slightlyLighter ].
  ^ revisedColor

5.4. whileTrue

Izvršava blok prijemnik sve dok je vrednost true:

[ ... ] whileTrue

Analogno, postoje i whileFalse i whileFalse:

5.5. Iteracije

Implementirane kao poruke.

Pitamo kolekciju da uradi iteraciju svojih elemenata:

#(1 2 -4 -86) do: [ :each | Transcript show: each abs printString; cr ]
> 1
> 2
> 4
> 86

5.6. Osnovne iteracije definisane nad kolekcijama

  • do: - iteracija
  • collect: - iteracija i mapiranje elemenata
  • select: - selekcija elemenata na osnovu predikata
  • reject: - eliminacija elemenata na osnovu predikata
  • detect: - vraća prvi koji zadovoljava uslov
  • detect:ifNone: - vraća prvi koji zadovoljava uslov ili podrazumevanu vrednost ukoliko takvog nema u kolekciji
  • includes: - test da li elemenat pripada kolekciji
  • … mnogi drugi
#(2 3 7) collect: [ :each | each raisedTo: 2 ]
> #(4 9 49)

#(2 9 7) detect: [ :i | (i \\ 3) = 0 ]
> 9

5.7. Interesantni primeri

3 timesRepeat: [ Transcript show: 'Hello' ; cr ].

Date today + 12 days.

Point linesOfCode.

Smalltalk allClasses size.

Smalltalk allClasses inject: 0 into: [ :sum :each | sum + each linesOfCode ].

VGTigerDemo runDemo.

SystemNavigation new browseAllSelect:
       [:m| m primitive isZero and: [m pragmas notEmpty]].

6. Bulovi izrazi i uslovi

6.1. Bulovi izrazi

  • true je jedinstvena instanca klase True
  • false je jedinstvena instanca klase False
  • Klase True i False nasleđuju klasu Boolean

U Pharo Bulovi izrazi nisu ništa specijalno:

  • & | not
  • or: and: - lazy
  • xor:
  • ifTrue:ifFalse:
  • ifFalse:ifTrue:

6.2. Eager i lazy evaluacija izraza

false & (1 error: 'crazy')
−> an error

Argument (1 error: 'crazy') se evaluira jer ova operacija ne koristi “lenju evaluaciju” (lazy).

false and: [ 1 error: 'crazy' ]
−> false "no error!"

Argument [ 1 error: 'crazy' ] se ne evaluira jer nije neophodno za određivanje vrednosti izraza - koristi se “lenja evaluacija”.

6.3. Uslovi

U Pharo uslovi su poruke koje se šalju Bulovim vrednostima i blokovima.

6.4. ifTrue:ifFalse je poruka

Weather isRaining
  ifTrue: [ self takeMyUmbrella ]
  ifFalse: [ self takeMySunglasses ]
  • Konceptualno ifTrue:ifFalse je poruka koja se šalje objektu koji ima Bulovu vrednost (ili je true ili je false).
  • Optimizovano od strane kompajlera.

6.5. ifTrue i ifTrue:ifFalse:

ifTrue: [] i ifTrue: [] ifFalse: [] su različite poruke.

LogicalFont>>forceItalicOrOblique
  self slantValue = 0
  ifTrue: [ slantValue := 1 ]

Analogno, ifFalse:[] i ifFalse: [] ifTrue: [] su različite poruke.

6.6. Uslovi: ifEmpty i ifNotEmpty:

Implementirano za kolekcije.

myProtocol
  ifEmpty: [ 'As yet unclassified' ]
> 'As yet unclassified' ili myProtocol

Implementacija:
Collection>>ifEmpty: aBlock
	^ self isEmpty 
		ifTrue: [ aBlock value ]
		ifFalse: [ self ]
self listItems
  ifNotEmpty: [ :aList | aList at: index ]
> element liste na indeksu "index" ili sama lista ukoliko je prazna

Implementacija:
Collection>>ifNotEmpty: aBlock
    ^self isEmpty
          ifTrue: [self]
          ifFalse: [aBlock cull: self] 
  • cull: - evaluira prijemnik sa jednim ili nula parametara u zavisnosti od toga koliko parametara prijemnik prihvata.

7. Klase i metode

7.1. System Browser

browser.png

7.2. Kreiranje klase

point_class.png

7.3. Kreiranje klase

Slanje poruke nadklasi

Object subclass: #Point
  instanceVariableNames: 'x y'
  classVariableNames: ''
  package: 'Kernel-BasicObjects'

7.4. Definicija metoda

  • Metode su javne (public)
  • Metode su virtualne (tj. pronalaze se u vreme izvršavanja)
  • Podrazumevano vraćaju self
messageSelectorAndArgumentNames
  "comment stating purpose of message"
  
  | temporary variable names |
  statements

7.5. Primer definicije metode

method_definition.png

7.6. Metoda podrazumevano vraća self

Game >> initializePlayers
  self players
  at: 'tileAction'
  put: ( MITileAction director: self )

je ekvivalentno sa:

Game >> initializePlayers
  self players
  at: 'tileAction'
  put: ( MITileAction director: self ).
  ^ self "<−− optional"

7.7. Metode klase

class_methods.png

  • Dugme Class služi za pregled i definiciju metoda klase.
  • Metode na nivou klase. Odgovor na poruke koje se šalju klasi.
Point class >> x: xInteger y: yInteger
  "Answer an instance of me with coordinates xInteger and yInteger."

  ^ self basicNew setX: xInteger setY: yInteger

8. yourself

8.1. Problem

Dodajemo 2 u skup:

Set new add: 2
>2

Rezultat izraza je 2 a ne skup!

8.2. Zašto?

Set>>add: newObject
  "Include newObject as one of the receiver's elements, but
  only if not already present. Answer newObject."
  [...]
  ^ newObject
  • Metod add: vraća argument a ne objekat
Set new add: 2
>2

8.3. Moguće rešenje

|s|
s := Set new.
s add: 2.
s

8.4. Kraće rešenje - yourself

Object >> yourself
^ self
Set new
  add: 2;
  yourself
> aSet
  • Poruke add: i yourself se šalju skupu
  • kaskada ; vraća objekat koji vraća poruka yourself - u našem slučaju skup.

8.5. Česta greška

Counter class >> withValue: anInteger
  self new
  value: anInteger;
  yourself
  • Counter withValue: 10 vraća Counter klasu umesto njenu instancu.

8.6. Zašto?

Counter class >> withValue: anInteger
  self new
  value: anInteger;
  yourself

je ekvivalentno sa:

Counter class >> withValue: anInteger
  self new
  value: anInteger;
  yourself.
  ^self

Gde je self prijemnik poruke withValue: tj. klasa Counter.

8.7. Rešenje

Counter class >> withValue: anInteger
  ^self new
  value: anInteger;
  yourself

9. Nasleđivanje i pretraga metoda (Method Lookup)

9.1. Osnove

Podklasa:

  • Može da doda stanje i ponašanje
  • Može da koristi stanje i ponašanje nadklase
  • Može da izvrši specijalizaciju i redefiniciju ponašanja nadklase

inheritance.png

9.2. Koren hijerarhije nasleđivanja

  • Možemo smatrati da je klasa Object korenska klasa svake klase.
  • Postoji i klasa ProtoObject ali je njena upotreba specijalna pa je nećemo razmatrati.

hierarchy.png

9.3. Osnove nasleđivanja

Nasleđivanje je:

  • Statičko za stanje (u vreme definisanja klase).
  • Dinamičko za ponašanje (u vreme izvršavanja).

9.4. Nasleđivanje varijabli instanci klasa

  • Dešava se za vreme definicije klase.
  • Izračunava se na osnovu:
    • Varijabli posmatrane klase.
    • Varijabli svih nadklasa.

inheritance.png

9.5. Nasleđivanje ponašanja

  • Dešava se u vreme izvršavanja
  • Metoda se traži:
    • Počevši od klase objekta prijemnika
    • Zatim u svim nadklasama uz lanac nasleđivanja.

method_lookup.png

9.6. Slanje i obrada poruka

Obrada poruke se obavlja u dva koraka:

  1. Pretraga odgovarajuće metode.
  2. Izvršavanje metode na objektu prijemniku.

message_sending.png

9.7. Semantika self ključne reči

  • self ključna reč se koristi u implementaciji metoda i uvek predstavlja objekat prijemnik.

self_example.png

  • Šta je rezultat izraza A new foo a šta izraza B new foo?
  • Šta je rezultat izraza A new bar a šta izraza B new bar?

9.8. Semantika super ključne reči

super_example.png

  • super predstavlja objekat prijemnik ali pretraga poruka započinje u nadklasi klase u kojoj se super nalazi.
  • Šta su rezultati izraza A new bar, B new bar i C new bar?

9.9. self se određuje dinamički

self_example.png

U metodi A>>bar kod ^self foo ne znamo do vremena izvršavanja na koji foo se poziv odnosi. To zavisi od klase konkretnog objekta prijemnika.

9.10. super se određuje statički

super_static.png

  • U vreme kompajliranja znamo da metoda B>>foo referencira A>>foo putem super.
  • Uvek počinjemo pretragu u nadklasi klase koja sadrži metodu koja koristi super.

9.11. Poruke koje nemaju odgovarajuću metodu

  • Ukoliko metoda nije pronađena standardnim mehanizmom pretrage, prijemniku se šalje poruka doesNotUnderstand
  • Podrazumevana implementacija u Object klasi signalizira izuzetak MessageNotUnderstood.

doesNotUnderstand.png

10. Implementacija Boolean tipa

10.1. Implementacija Boolean tipa

U Pharo Boolean tip ima odličan dizajn:

  • &, |, not - eager
  • or:, and: - lazy
  • ifTrue:, ifTrue:ifFalse, ...

10.2. Za razmišljanje

U svetu gde imate samo dve vrednosti: true i false i razmenu poruka

  • kako implementirati not?
  • kako implementirati or?

10.3. not

false not
> true
true not
> false

10.4. Bez upotrebe uslova

Rešenje ne koristi uslove.

Uslovi bi svakako morali da budu bazirani na Bulovom tipu.

10.5. Rešenje koristi tri klase

  • Boolean (apstraktna), True i False
  • true je singlton instanca klase True
  • false je singlton instanca klase False

boolean.png

10.6. Kako iskazujemo izbor u OOP?

U OOP, izbor iskazujemo:

  • Definisanjem klasa sa kompatibilnim metodama
  • Slanjem poruke instanci takve klase

Primer:

x open
  • x može biti fajl, prozor, alat…
  • Metod se selektuje u zavisnosti od klase objekta x
  • U Python-u poznato kao Duck Typing

10.7. Implementacija not operacije

False >> not
  "Negation −− answer true since the receiver is false."
  ^ true
True >> not
  "Negation −− answer false since the receiver is true."
  ^ false

10.8. Hijerarhija implementacije

boolean_not_hierarchy.png

10.9. Pretraga poruke (message lookup) je izbor prave metode

boolean_not_lookup.png

10.10. Implementacija Boolean klase

  • Boolean je abstraktna klasa
  • Podklase su True i False koje implementiraju:
    • logičke operacije & i not
    • kontrolne strukture and:, or:, ifTrue:, ifFalse:, ifTrue:ifFalse:, ifFalse:ifTrue:
Boolean>>not
  "Abstract method. Negation: Answer true if the receiver is
   false, answer false if the receiver is true."

  self subclassResponsibility

10.11. Ponašanje Or operacije

true | true −> true
true | false −> true
true | anything −> true
false | true −> true
false | false −> false
false | anything −> anything

10.12. Implementacija Or operacije u Boolean klasi

Boolean >> | aBoolean
  "Abstract method. Evaluating Or: Evaluate the argument.
   Answer true if either the receiver or the argument is true."

  self subclassResponsibility

10.13. Implementacija Or operacije u klasi False

false | true −> true
false | false −> false
false | anything −> anything
False >> | aBoolean
  "Evaluating Or −− answer with the argument, aBoolean."
  ^aBoolean

10.14. Implementacija Or operacije u klasi True

true | true −> true
true | false −> true
true | anything −> true
True >> | aBoolean
  "Evaluating Or −− answer true since the receiver is true."
  ^true

A pošto je prijemnik true možemo uraditi sledeće:

True >> | aBoolean
  "Evaluating Or −− answer true since the receiver is true."
  ^self

11. Reference