Oficjalnie stwierdzam, że kocham nowe ficzery z Java'y 5.0 :-)
Generyki są wspaniałe, varargsy również, for each także, a wczoraj naprawdę poznałem i polubiłem enumy.
Jedno z przykazań poprawnego obiektowego tworzenia aplikacji jest to by jak najrzadziej używać wartości prymitywów, a już w ogóle unikać jak ognia ich porównywania.
Teraz "mała" dygresja.
Fanatycy wydajności kręcą zwykle nosami przy tym punkcie, krzycząc o tym, że prymitywy są szybsze. Zwykle zapominają tu o jednej z zasad programowania Unix'ów, która można swobodnie przenieść do zasad programowania w ogóle, która mówi:
"Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is."
za http://www.faqs.org/docs/artu/ch01s06.html
Porównanie prymitywów jest może i szybsze, ale zwykle zysk w prędkości nie rekompensuje problemów, które mogą powstać. Dlatego w OOP zaleca się używanie gdzie tylko się da typów złożonych, między innymi dlatego, że porównywanie jest możliwe tylko między obiektami, które znajdują się w tej samej gałęzi dziedziczenia.
Używając prymitywów możemy mieć klasę Zwierze, która ma pola rodzajPozywienia i iloscNog:
public class Zwierze
{
// Definicje możliwych rodzajów pożywienia:
public final static int FRYTKI = 0;
public final static int ZIEMNIAKI = 1;
public final static int SERKI_TOPIONE = 2;
public int rodzajPozywienia;
public int iloscNog;
[...]
};
Porównanie prymitywów jest może i szybsze, ale zwykle zysk w prędkości nie rekompensuje problemów, które mogą powstać. Dlatego w OOP zaleca się używanie gdzie tylko się da typów złożonych, między innymi dlatego, że porównywanie jest możliwe tylko między obiektami, które znajdują się w tej samej gałęzi dziedziczenia.
Używając prymitywów możemy mieć klasę Zwierze, która ma pola rodzajPozywienia i iloscNog:
public class Zwierze
{
// Definicje możliwych rodzajów pożywienia:
public final static int FRYTKI = 0;
public final static int ZIEMNIAKI = 1;
public final static int SERKI_TOPIONE = 2;
public int rodzajPozywienia;
public int iloscNog;
[...]
};
Widać, że rodzajów pożywienia mogą być 3 rodzaje, ilość nóg może być dowolna.
Nic nas jednak poza zdrowym rozsądkiem nie powstrzymuje w tym przypadku przed porównywaniem rodzaju pożywienia z ilością nóg.
Całkiem poprawnym kodem jest więc:
if (rodzajPozywienia==iloscNog) robCos();
My wiemy, że to bez sensu ale kompilator nie.
Do tego dochodzi to, że jeżeli ktoś nam wpisze w rodzajPozywienia wartość większą niż przewidziana przez nas znów zaczynają się problemy.
W OOP dlatego powinniśmy używać gdzie się da typów złożonych. Powyższy przykład mógłby wyglądać następująco:
public class Zwierze
{
public static class RodzajPozywienia
{
private int rodzajPozywienia;
public RodzajPozywienia(int rodzajPozywienia)
{
this.rodzajPozywienia=rodzajPozywienia;
}
}
public final static RodzajPozywienia FRYTKI = new RodzajPozywienia(0);
public final static RodzajPozywienia ZIEMNIAKI = new RodzajPozywienia(1);
public final static RodzajPozywienia SERKI_TOPIONE = new RodzajPozywienia(2);
public RodzajPozywienia rodzajPozywienia;
public int iloscNog;
[...]
}
Teraz już kod:
if (rodzajPozywienia==iloscNog) robCos();
nie zostanie skompilowany.
Mamy postęp, ale ileż pisania więcej, a do tego jakoś to mało czytelne.
W tym miejscu pojawiają sie enumy :-)
public class Zwierze
{
public enum RodzajPozywienia
{
FRYTKI, ZIEMNIAKI, SERKI_TOPIONE
};
public RodzajPozywienia rodzajPozywienia;
public int iloscNog;
[...]
}
Krótko i treściwie :-)
Jeżeli jeszcze chcielibyśmy np. dodać kaloryczność pożywienia [dane wezmę z sufitu :-)] to jest to bardzo proste:
public enum RodzajPozywienia
{
FRYTKI(100.0),
ZIEMNIAKI(75.4),
SERKI_TOPIONE(302.1);
private double kalorycznosc;
private RodzajPozywienia(double kalorycznosc)
{
this.kalorycznosc=kalorycznosc;
}
public double getKalorycznosc()
{
return kalorycznosc;
}
}
Trochę się to rozciąga, ale nadal jest dość czytelne, a w enumie mamy od razu dodatkowe informacje.
Enumy wymagają chwili by się ich nauczyć i je zrozumieć, ale czas zużyty na ich poznanie jest wart "zużycia".
Podobne postybeta
Cieniowanie Gourauda w JavaScript part 2 - przyśpieszamy :-)
Javozagadka ;-)
Spectre powinno działać nawet w Java'ie ;-)
Java 8 to taki wodospad ;-)
Groch z kapustą, czyli co daje mieszanie OOP z programowaniem strukturalnym
Brak komentarzy:
Prześlij komentarz