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();
}
}