klasy i obiekty 181 Kb May 31 2008 05:31:49 PM
Transkrypt
klasy i obiekty 181 Kb May 31 2008 05:31:49 PM
Dokumentacja do API Javy http://java.sun.com/j2se/1.5.0/docs/api/ Klasy i obiekty Klasa – jest to struktura zawierająca dane (pola), oraz funkcje operujące na tych danych (metody). Klasa jest rodzajem szablonu na podstawie którego tworzone są obiekty (instancje) tej klasy. Jeżeli przyjęlibyśmy, że foremka do zabawy w piasku jest klasą, to „babki” wykonane za pomocą tej foremki nazwalibyśmy obiektami tej klasy. Z reguły dostęp do pól składowych klasy możliwy jest tylko przez odpowiednie metody składowe danej klasy. Tego typu proces izolacji danych przed przypadkową i/lub niewłaściwą modyfikacją nazywamy enkapsulacją. (Zamykaniem w kapsułach – obiekt jest tego typu kapsułą, która przechowuje dane i zapobiega dostępowi nich w inny sposób jak przez odpowiednie metody) Tworzenie obiektu danej klasy Do przechowywania łańcuchów znakowych używaliśmy klasy String. W jaki sposób tworzymy obiekty tej klasy: String tekst; to jeszcze nie jest obiekt, to tylko „pusta” referencja do obiektu (nie wskazuje na nic). String tekst = ”To dopiero jest obiekt”; Powyższa deklaracja zmiennej tworzy obiekt typu String i umieszcza w zmiennej tekst referencję do niego. Obiekty danej klasy możemy tworzyć także w inny sposób używając operatora new. String tekst = new String(”To takżeobiekt”); Wykorzystywanie istniejących klas Tworzymy obiekt istniejącej w pakiecie java.lang.utils klasy Date. Do tworzenia obiektów danej klasy używamy operatora new. import java.util.Date; public class TestDaty { public static void main(String[] args) { } } Date dzisiejszaData = new Date(); System.out.println(dzisiejszaData); Wykorzystywanie istniejących klas cd. import java.util.*; class TestKalendarza { public static void main(String[] args) { GregorianCalendar dataZKalendarza = new GregorianCalendar(); int rok = dataZKalendarza.get(Calendar.YEAR); int miesiac = dataZKalendarza.get(Calendar.MONTH)+1; int dzien = dataZKalendarza.get(Calendar.DAY_OF_MONTH); System.out.println(rok+" : "+miesiac+" : "+dzien); } } Tworzenie własnej klasy Ogólna postać klasy wygląda następująco: class NazwaKlasy { konstruktor1 konstruktor2 ... metoda1 metoda2 ... pole1 pole2 } konstruktor Konstruktor to specjalna metoda wywoływana podczas tworzenia obiektu. Własności konstruktorów: ● Nazwa konstruktora musi być taka sama jak nazwa klasy ● Konstruktor może być wywołany tylko przez operator new ● Klasa może posiadać więcej niż jeden konstruktor ● Konstruktor nie zwraca wartości ● Konstruktor może posiadać zero lub więcej parametrów Konstruktor cd. Konstruktor wykorzystywany jest do inicjalizacji obiektów danej klasy. Jeżeli nie stworzymy konstruktora, to zostanie stworzony konstruktor domyślny, który inicjalizuje zmienne w następujący sposób: ● ● ● Liczbą przypisuje wartość zero Wartością logicznym false Referencją null Konstruktor cd. Możemy sami stworzyć konstruktor domyślny (bezparametrowy), który określi wartości początkowe naszych pól w określony przez nas sposób (zalecane jest tworzenie własnych domyślnych konstruktorów) class klasa { klasa() { pole1 = 0; pole2 = ”wartość”; ... } } Tworzenie własnej klasy - przykład class Okrag { Okrag() //konstruktor domyślny { this.promien=0; } Okrag(double r) //inny konstruktor { this.promien=r; } } double pole() //metoda { return Okrag.PI*this.promien*this.promien; } double promien; //pola static final double PI=3.14; Wykorzystanie stworzonej klasy public class Main { public static void main(String[] args) { Okrag o = new Okrag(10); System.out.println("Pole okręgu wynosi :"+o.pole()); } } Inny przykład public class Program { public static void main(String[] args){ String tmp = JOptionPane.showInputDialog("Podaj promień : "); double p = Float.parseFloat(tmp); Okrag o = new Okrag(p); String s = "Pole koła o promieniu "+p+" = "+o.pole(); JOptionPane.showMessageDialog(null,s); } } Modyfikatory dostępu Określają kto i w jaki sposób będzie miał dostęp do klas i/lub ich składowych. Rodzaje modyfikatorów: Modyfikatory klas : ➢ public : klasa dostępna dla wszystkich innych klas ➢ final : klasa finalna (nie można po niej dzisdziczyć) ➢ abstract : klasa „abstrakcyjna” zawierająca „puste” metody ➔ Modyfikatory pól i metod ➢ public : nieograniczony dostęp ➢ protected : dostęp rodzimego pakietu i klas dziedziczących ➢ private : dostęp tylko dla metod danej klasy ➢ : dostęp dla pakietu rodzimego ➔ Kompozycja Jeżeli w definicji klasy użyjemy jako pól obiektów innych klas to powstała w ten sposób konstrukcja nosi nazwę kompozycji: class Samochód { } Silnik silnikSamochodu; Zawieszenie zawieszenieSamochodu; Nadwozie nadwizieSamochodu dziedziczenie Dziedziczenie – tworzenie klas na bazie juz istniejących pozwalających rozszerzyć lub/i zmienić ich funkcjonalność. Ogólny schemat dziedziczenia: class klasa_pochodna extends klasa bazowa { ... // pola i metody będące uzupełnieniem klasy bazowej // przeładowane metody } ... Przeładowanie metody Jeżeli w podklasie (klasie potomnej) zdefiniujemy metodę o takiej samej nazwie jak metoda klasy bazowej, to obiekty klasy potomnej będą używały nowej „wersji” metody zamiast metody klasy bazowej. Sytuację taką nazywamy przeładowaniem metody. Przykład przeładowania class Pracownik { ... int pobierzWynagrodzenie() { return pensja; } } ... private int pensja; class Kierownik extends Pracownik { ... int pobierzWynagrodzenie() { return super.pobierzWynagrodznie + dodatekFunkcyjny; } } private int dodatekFunkcyjny; Słowo kluczowe super W poprzednim przykładzie użyliśmy słowa kluczowego super w celu dostępu do metody klasy nadrzędnej. (jest to odpowiednik konstrukcji NazwaKlasyBazowej::nazwaMetody() w c++ ) W naszym przykładzie użycie konstrukcji: class Kierownik extends Pracownik { int pobierzWynagrodzenie(){ return pensja + dodatekFunkcyjny; } } Zwróciłoby błąd ze względu na fakt, że pole pensja jest polem prywatnym klasy Pracownik i dostęp do niego jest mozliwy jedynie przez metodę pobierzWynagrodzenie(). Dlaczego więc nie tak: int pobierzWynagrodzenie(){ return pobierzWynagrodzenie() + dodatekFunkcyjny; } ponieważ w ten sposób zapętlimy program. Przykład przeładowania: Załóżmy że mamy klasę Pracownik reprezentującą pracowników danej firmy, każdy z pracowników otrzymuje wynagrodzenie. Niech metoda pobierzWynagrodzenie() zwraca pensję pracownika. Dodatkowo stanowiska kierownicze otrzymują dodatek funkcyjny. Jak będzie wyglądała metoda pobierzWynagrodzenie() dla klasy Kierownik ? Pracownik Kierownik Wywołanie konstruktora nadklasy Tworząc konstruktor klasy potomnej zaleca się wywołanie konstruktora nadklasy. class Kierownik extends Pracownik { Kierownik (String i, String n, int pensja, int dodatek) { super(i,n,p); dodatekFunkcyjny = dodatek; } private int dodatekFunkcyjny; } Uwaga: wywołanie konstruktora nadklasy musi nastąpić jako pierwsze w konstruktorze podklasy. Klasy finalne Jeżeli chcemy aby jakaś klasa była ostatnią w hierarchii i nie można było po niej dziedziczyć to oznaczamy ją modyfikatorem final. W naszej przykładowej hierarchii klas reprezentujących strukturę firmy za klasę finalną możemy uznać klasę reprezentującą prezesa. final class Prezes extends Dyrektor { ... } Metody finalne Jeżeli w danej klasie zdefiniujemy metodę jako finalną to w żadnej podklasie nie będzie można jej przładować. W naszym przykładzie moglibyśmy tak postąpić na przykład z metodą zwracającą nazwisko pracownika, ponieważ nie zależnie od stanowiska nazwisko zawsze wygląda tak samo. class Pracownik { ... public final String podajNazwisko() ... } Klasy abstrakcyjne Oznaczamy je słowem kluczowym abstract, ● są fundamentem do budowy innych klas, ● nie mogą posiadać swoich instancji (obiektów), ● mogą posiadać metody abstrakcyjne W naszym przykładzie abstrakcyjną klasą mogłaby być klasa reprezentująca wszystkie osoby abstract class Osoba { ... } ● interfejsy Interfejs jest „przepisem” na to co klasa powinna robić, bez określania sposobu w jaki powinna to robić. W innym ujęciu interfejs jest zbiorem wymagań dotyczących klas które chcą go implementować (dostosowywać się do interfejsu). Interfejsy cd. Jeżeli chcielibyśmy, aby obiekty tworzonych przez nas klas można było np. sortować z użyciem tej samej metody to musielibyśmy wyposażyć je w uniwersalną metodę która porównuje obiekty danej klasy. Jak sprawić aby wszystkie tworzone przez nas klasy musiały posiadać określoną metodę? Należy stworzyć interfejs, który będzie implementowany przez wszystkie klasy. Przykład interfejsu public interface daSiePosortowac { int porownaj(object inny); } Jak widać interfejs daSiePosortowac nie implementuje metody porownaj. Implementacji metody porównaj musimy dokonać wewnątrz klas, które będą implementowały nasz interfejs. Właściwości interfejsów Interfejsy nie są klasami, ● Interfejsy nie posiadają zmiennych ● Interfejsy mogą posiadać stałe (są one automatycznie typu public static final) ● Wszystkie metody interfejsu są publiczne ● Nie możemy tworzyć obiektów interfejsu przy użyciu operatora new. ● Możemy deklarować zmienne interfejsów, które będą wskazywały na obiekty implementujące dany interfejs ● Wiele klas może implementować jeden interfejs ● Jedna klasa może implementować wiele interfejsów ● Interfejs – rzeczywisty przykład Chcemy aby wszystkie tworzone przez nas klasy podawały nazwisko autora poprzez metodę autor(). Tworzymy interfejs Copyright: public interface Copyright { void autor(); } Implementacja interfejsu class Rownanie implements Copyright { ... void autor () { System.out.println(” Jan Kowalski 2006”); } ... } Dlaczego interfejs Dlaczego nie użyć klasy abstrakcyjnej zamiast interfejsu? Ponieważ większość tworzonych przez nas klas rozszerza już jakieś klasy bazowe, a w jezyku Java nie istnieje wielokrotne dziedziczenie (jak np. w c++). Konstrukcja typu: class Pracownik extends Osoba, Copyright wygeneruje błąd. Natomiast class Pracownik extends Osoba implements Copyright jest poprawną konstrukcją programistyczną w javie. import java.awt.*; import javax.swing.*; Rzeczywisty przykład public class Main { public Main() { } public static void main(String[] args) { beep b = new beep(); Timer t = new Timer(1000,b); do { t.start(); }while (JOptionPane.showConfirmDialog(null,"Zakończyć beepanie ?") !=0); t.stop(); } } class beep implements ActionListener { public void actionPerformed(ActionEvent e){ Toolkit.getDefaultToolkit().beep(); } }