"Wiem, że nie wiem" to tzw. poziom świadomej niekompetencji kiedy miejsce ignorancji zastępują pytania bez odpowiedzi.
I takie właśnie pytanie pojawiło się na ostatnim warsztacie - jak dobrze zmodyfikować zachowanie klasy przy pomocy Traita tak by ona nic o tym nie wiedziała. Na miejscu niestety nie udało mi się odpowiedzieć ale teraz mamy drugą szansę.
Ortogonalne
Ortogonalne to to samo co prostopadłe ale brzmi mądrzej. W tym przypadku nie ma modyfikacji zachowania klasy jako takiej ale Trait dodaje zupełnie nową funkcjonalność - tutaj logowanie.
abstract class Actor {
def receive(s:String):Unit
}
//wersja oryginalna
class EchoActor extends Actor {
override def receive(s:String)=println(s"echo $s")
}
//wersja z mixinem
class EchoActor extends Actor with Logging{
override def receive(s:String)={
logger.log(s)
println(s"echo $s")
}
}
trait Logging{
class Logger{
def log(s:String)=println(s"LOGGING : $s")
}
val logger=new Logger
}
new EchoActor().receive("message")
I teraz pytanie jak to zrobić by dodać to logowanie ale bez modyfikacji EchoActor?
Podejście pierwsze - self type
Trzeba trochę eksperymentować w życiu i nie zrażać się tym, że czasem nie wychodzi. Bo teraz to co napiszę nie zadziała.
//ten kawalek/mechanizm "self:Actor=> " nazywa się "self-type" i daje traitowi
//wiedzę, z jaką klasą będzie zmiksowany
trait NonOrthogonalLogging1{self:Actor=>
def cosTam(){
self.receive("aaa")
}
//chociaz nie dziedziczymy po aktorze to trzeba dać override bo inaczej będzie się walić przy miksowaniu
override def receive(m:String):Unit={
println(s"INFO : ${m}")
//nie można tutaj użyć super bo teoretycznie dziedziczymy z AnyRef
self.receive(m)
}
}
//no i koniec końców nic niespodziewanego się nie dzieje, "self.receive" wywołuje metodę z traita a nie z klasy i cały program się zapętla.
val echo=new EchoActor() with NonOrthogonalLogging1
echo.receive("test")
Podejście drugie - dziedziczenie klasy abstrakcyjnej
trait NonOrthogonalLogging2 extends Actor{self:Actor=>
//to jest dziwne, trzeba dać abstract bo inaczje kompilator sie pluje, ze receive z nadklasy jest abstract.
abstract override def receive(m:String):Unit={
println(s"INFO : ${m}")
super.receive(m)
}
}
class EchoActor extends Actor{
def receive(m:String)=println(s"ECHO ${m}")
}
//no i to już działa
val echo=new EchoActor() with NonOrthogonalLogging2
echo.receive("test")
//INFO : test
//ECHO test
Oczywiście, jeśli ktoś wie jak to zrobić lepiej niech śmiało da znać.
Warsztat
Na warsztat http://www.meetup.com/Java-User-Group-Lodz/events/221347512/ zapisało się 25 osób +15 jest na liście oczekujących co daje 40 osób zainteresowanych nauką Scali. Fajnie, że ludzie są zmotywowani do nauki Scali i to także motywuje mnie, żeby robić te warsztaty.
Niedawno na EDX był kurs szczęścia- dosłownie kurs szczęścia EDX : Science of hapiness. - bazujący na ciekawym dziale psychologii czyli Psychologii pozytywnej. Motyw działalności w lokalnych społecznościach pojawiał się tam dosyć często.
Więcej można o tym poczytać sobie też tutaj : http://www.actionforhappiness.org/10-keys-to-happier-living/local-community/details. Interakcje społeczne zwiększają nasilenie wytwarzania oksytocyny, która jest hormonem antagonistycznym do kortyzolu co generalnie poprawia nastrój i tak dalej.

Na luzie:d
OdpowiedzUsuń