[WikiDyd] [TitleIndex] [WordIndex

Tworzenie i używanie klas języku Java

Program w Javie składa się z klas. Niektóre klasy są przez autora programu tworzone, ale pisanie programu polega raczej na wykorzystywaniu klas już istniejących. Siłą Javy jest potężna biblioteka klas o rozmaitych zastosowaniach: od implementacji rozmaitych struktur danych i algorytmów, przez bibliotekę graficzną, umożliwiającą pisanie przenośnych [http://pl.wikipedia.org/wiki/GUI GUI], aż po klasy służące do tworzenia programów rozproszonych, [http://pl.wikipedia.org/wiki/Applet apletów], [http://pl.wikipedia.org/wiki/Serwlet serwletów] i [http://en.wikipedia.org/wiki/Midlet midletów].

Złożoność narzędzi dostępnych dla osób tworzących programy w Javie ilustruje rysunek (zaczerpnięty ze stron dokumentacji Javy - java.sun.com):

http://www.iem.pw.edu.pl/~jstar/dyd/images/j2se5.gif

Na klasę można patrzeć z punktu widzenia jej twórcy lub jej ,,konsumenta". W obu przypadkach najważniejszy jest interfejs klasy.

Spójrzmy na jedną z klas z programu prezentowanego na poprzednim wykładzie: z punktu widzenia użytkownika istotny jest następujący schemat (zgodny z językiem [http://pl.wikipedia.org/wiki/UML UML])

+---------------------+
|DoubleStack          |      <- nazwa klasy
+---------------------+
|push( double ) : void|      <- interfejs - funkcje (metody)
|pop() : double       |
+---------------------+

Z punktu widzenia twórcy tej klasy istotne będzie też określenie danych przechowywanych przez obiekty klasy:

+---------------------+
|DoubleStack          |      <- nazwa klasy
+---------------------+
|s : double []        |      <- właściwości (dane)
|sp : int             |
+---------------------+
|push( double ) : void|      <- interfejs
|pop() : double       |
+---------------------+

Różnica w dwóch powyższych diagramach jest widoczna, ale warto też zdawać sobie z niej sprawę: programowanie obiektowe pozwala ukryć szczegóły nieistotne na określonym poziomie abstrakcji - użytkownika klasy DoubleStack nie musi (a nawet nie powinno) obchodzić, jak obiekt tej klasy ,,jest zrobiony" - dla niego ważne jest, jak obiekt działa.

Mówiliśmy już, że takie projektowanie kodu ma wiele zalet:

Dodatkowa zaleta, którą widać dobrze przy analizie całego programu ONP to możliwość zdefiniowania takich pojęć (klas), że program jest bardzo zbliżony do rzeczywistości: posługujemy się klasami, których nazwy (i nazwy ich metod) są bardzo bliskie terminologii dziedziny, którą program ma symulować.

Z czego składa się klasa?

Z pól (własności) (czyli danych) i z metod (czyli funkcji).

Własności obiektu określaja jego stan, który powinien być modyfikowany tylko przez odpowiednie metody (a nie przez kod zawarty w innych klasach). Aby zabezpieczyć pola przed dostępem z zewnątrz, deklarujemy je jako prywatne (private).

class Komputer {
  private Firma producent;
  private String typ;
  private long numerSeryjny;
  private String nazwa;
  private Osoba właściciel;
  ...

Metody służą do manipulacji obiektami. W terminologii obiektowej mówimy, że obiekty wysyłają do siebie komunikaty przez wywoływanie odpowiednich metod. Np.:

  Telefon mójTel;   // zwróćmy uwagę, że w Javie można używać polskich liter!
  mójTel.dodajKontakt( "Ala", "+41 123456789" );
  mójTel.dzwoń( "Ala" );
  mójTel.odsłuchajSekretarkę();
  ...

Przykład ,,własnej" klasy:

   1 /** Przykładowa klasa reprezentująca kontakt (parę: <imię, telefon>).
   2     @author J. Starzynski (jstar@iem.pw.edu.pl)
   3     @version 0.2
   4 */
   5 public class Kontakt {
   6   private String imie;
   7   private int tel;
   8 
   9   Kontakt( ) {
  10     imie= null;
  11     tel = 0;
  12   }
  13 
  14   Kontakt( String i, int t ) {
  15     imie= i;
  16     tel = t;
  17   }
  18 
  19   public int getTel() {
  20     return tel;
  21   }
  22 
  23   public void setTel( int tel ) {
  24     this.tel= tel;
  25   }
  26 
  27   public String imie() {
  28     return imie;
  29   }
  30 
  31   public void imie( String imie ) {
  32     this.imie= imie;
  33   }
  34 
  35   public String toString() {
  36     return "Tel( " + imie + " )= " + tel;
  37   }
  38 
  39   public static void main( String [] args ) {
  40     Kontakt k= new Kontakt();
  41 
  42     for( int i= 0; i < args.length; i++ ) {
  43       k.imie( args[i] );
  44       k.setTel( 1234567 );
  45       System.out.println( k.imie() + ": " + k.getTel() );
  46     }
  47 
  48     for( int i= 0; i < args.length; i++ ) {
  49       k= new Kontakt( args[i], 7654321 );
  50       System.out.println( k );
  51     }
  52   }
  53 }

Przykład klasy wykorzystującej klasę Kontakt:

   1 /** Przykładowa klasa agregująca kontakty.
   2     @author J. Starzynski (jstar@iem.pw.edu.pl)
   3     @version 0.1
   4 */
   5 public class Notes {
   6   private Kontakt[] k;
   7   private int n;
   8 
   9   Notes() {
  10     k= new Kontakt[10];
  11     n= 0;
  12   }
  13 
  14   public Kontakt k( int i ) {
  15     if( i > 0 && i <= n )
  16       return k[i-1];
  17     else
  18       return null;
  19   }
  20 
  21   public Kontakt k( String imie ) {
  22     for( int i= 0; i < n; i++ )
  23       if( k[i].imie().equals( imie ) )
  24         return k[i];
  25     return null;
  26   }
  27 
  28   public int tel( int i ) {
  29     if( k(i) != null )
  30       return k(i).getTel();
  31     else
  32       return 0;
  33   }
  34 
  35   public int tel( String imie ) {
  36     for( int i= 0; i < n; i++ )
  37       if( k[i].imie() == imie )  // tu jest bd !
  38         return k[i].getTel();
  39     return 0;
  40   }
  41 
  42   public void nowy( Kontakt nowy ) {
  43     if( n == k.length ) {
  44       Kontakt [] nk= new Kontakt[2*n];
  45       for( int i= 0; i < n; i++ )
  46         nk[i]= k[i];
  47       k= nk;
  48     }
  49     k[n++]= nowy;
  50   }
  51 
  52   public void usuń( int i ) {
  53     if( i > 0 && i <= n ) {
  54       for( int j= i-1; j < n-1; j++ )
  55         k[j]= k[j+1];
  56       n--;
  57     }
  58   }
  59 
  60   public void usuString imie ) {
  61     for( int i= 0; i < n; i++ )
  62       if( k[i].imie().equals( imie ) ) {
  63         for( int j= i; j < n-1; j++ )
  64           k[j]= k[j+1];
  65         n--;
  66       }
  67   }
  68 
  69   public String toString() {
  70     String s= "Liczba wpis� " + n + "\n";
  71     for( int i= 0; i < n; i++ )
  72       s += "\t" + k[i] + "\n";
  73     return s;
  74   }
  75 
  76   public int ile() {
  77     return n;
  78   }
  79 
  80   public static void main( String [] args ) {
  81     Notes n= new Notes();
  82     for( int i= 0; i < args.length; i++ )
  83       n.nowy( new Kontakt( args[i], 7654321+i ) );
  84 
  85     System.out.println( n );
  86 
  87     String x= n.k( n.ile() / 2 + 1 ).imie();
  88 
  89     System.out.println( "W srodku: " + x );
  90     System.out.println( "\ttelefon: " + n.tel( x ) );
  91 
  92     n.usuń( x );
  93 
  94     System.out.println( "Po usuni�iu " + x );
  95     System.out.println( n );
  96 
  97   }
  98 }

Reguły dostępu

Pola statyczne.

Pola prywatne, pakietowe, publiczne.

Inicjalizacja obiektów

Inicjalizacja pól.

Konstruktory

Bloki inicjujące

Niszczenie obiektów

Obiekty to referencje.

Odśmiecacz.

Finalize

Przykład

Klasa Visa

   1 import java.util.*;
   2 
   3 /** Klasa Visa demonstruje:
   4   - ograniczanie liczby obiektów danej klasy
   5   - zwalnianie zasobów i zastosowanie finalize do kontroli tego procesu
   6   - zastosowanie standardowej kolekcji ArrayList
   7 */
   8 
   9 public class Visa {
  10   private int no;
  11   private int pin;
  12 
  13   static ArrayList<Integer> reservedPins= new ArrayList<Integer>();
  14 
  15   static int nextNo= 1;
  16 
  17   static final int maxVisas = 8;
  18 
  19   { // blok inicjujący (błędny!)
  20     no= nextNo++;
  21     do
  22       pin= Math.abs( (new Random()).nextInt() ) % maxVisas;
  23     while( reserved( pin ) );
  24     reservedPins.add( pin );
  25   }
  26 
  27   public String toString() {
  28     return "# " + no +", PIN: " + pin;
  29   }
  30 
  31   private static boolean reserved( int pin ) {  // czy pin jest zarezerwowany?
  32     return reservedPins.indexOf( pin ) >= 0;
  33   }
  34 
  35   static String reservedPins() { // lista zarezerwowanych pinów
  36     return reservedPins( 0, reservedPins.size()-1 );
  37   }
  38 
  39   static String reservedPins( int s, int e ) { // wersja przeciążona - fragment kolekcji
  40     StringBuffer str= new StringBuffer();
  41     for( int i= s; i <= e; i++ )
  42       str.append( reservedPins.get(i) + ", " );
  43     return str.toString();
  44   }
  45 
  46   public void dispose() { // zwalnia pin bieżącej karty
  47     int i= reservedPins.indexOf( pin );
  48     if( i >= 0 )
  49       reservedPins.remove( i );
  50     else
  51       System.err.println( "Illegal card: " + this );
  52   }
  53 
  54   protected void finalize() {
  55     if( reserved( pin ) ) {
  56       System.err.println( "\n\n" + this.getClass().getName() + " error:" );
  57       System.err.println( "\tCard " + this + " was not disposed\n" );
  58     }
  59   }
  60 
  61   public static void main( String [] args ) throws Exception {
  62     final int ntest= args.length > 0 ? Integer.parseInt( args[0] ) : 10;
  63     Visa bank[]= new Visa[ntest];
  64 
  65     System.out.println( "Creating " + ntest + " Visas" );
  66     for( int i= 0; i < ntest; i++ )
  67       bank[i]= new Visa();
  68 
  69     System.out.println( "Reserved pins: " + Visa.reservedPins() );
  70   
  71     for( int i= 0; i < ntest; i++ )
  72       System.out.println( bank[i] );
  73 
  74     System.out.println( "\nRejecting " + bank[0] + "\n" );
  75     System.out.println( "\nRejecting " + bank[ntest-1] + "\n" );
  76     bank[0].dispose();
  77     bank[0]= null;
  78     bank[ntest-1]= null;
  79 
  80     for( int i= 0; i < ntest; i++ )
  81       System.out.println( bank[i] );
  82 
  83     System.out.println( "Reserved pins: " + Visa.reservedPins() );
  84 
  85     System.out.println( "\nGarbage collecting\n" );
  86     System.gc();
  87     System.out.println( "Reserved pins: " + Visa.reservedPins( ) );
  88   }
  89 }

Więcej przykładów: j3.jar

Efektywność implementacji

Do zrobienia


2015-09-23 06:44