Programowanie w Java Charakterystyka języka Smalltalk OOP

Transkrypt

Programowanie w Java Charakterystyka języka Smalltalk OOP
Charakterystyka języka Smalltalk
1.
2.
Programowanie w Java
K.Barteczko: Ćwiczenia z Java. Wykłady i ćwiczenia, MIKOM,
Warszawa 2000.
B. Eckel: Thinking in Java. Wydanie trzecie. Edycja polska. Helion,
2003
http://kmeif3.kmeif.pwr.wroc.pl/~jpek/javaAPI/index.html
Everything is an object. (wyjątek typy proste)
A program is a bunch of objects telling each
other what to do by sending messages.
3. Each object has its own memory made up of
other objects. (kompozycja)
4. Every object has a type. (instance of class)
5. All objects of a particular type can receive the
same messages.
• Boch: „An object has state, behavior
and identity”
OOP
Interfejs obiektu
• Podstawowe zadanie w programowaniu
obiektowym polega na tworzeniu nowych typów
danych (klas).
• Klasy opisują zbiory obiektów o identycznych
charakterystykach i zachowaniu.
• Programowanie obiektowe wywodzi się z
symulacji (Simula-67) i to „naśladownictwo”
rzeczywistości wyraŜa się w próbie
projektowania modeli programowych
elementów, które występują w danej dziedzinie
z zachowaniem odpowiedniej dokładności
odwzorowania.
• UŜyteczność obiektów sprowadza się do
tego, Ŝe są one w stanie wykonać pewną
liczbę określonych poleceń.
• Repertuar tych poleceń jest określony
przez definicję typu (klasy) i jest
nazywany interfejsem (interface)
1
Wykonaj polecenie twoja sprawa jak
Light lt = new Light(); // tworzymy obiekt typy/klasy Light
lt.on(); //polecenie do obiektu przekazujemy „składając”
//referencję (lt) z nazwą polecenia (on) za pomocą kropki
Tworzenie i wykorzystywanie usług
• Celem programowania jest wytworzenie
albo lepiej odszukanie w dostępnych
bibliotekach takiego zbioru obiektów,
które dostarczają usług , które
satysfakcjonują wymagania uŜytkownika
(rozwiązują dany problem)
• Traktuj obiekty jak źródła usług
Zadania programistyczne
Specyfikatory dostępu
• Kreator klas
• Konsument klas
• private – dostęp tylko dla projektanta klasy,
• Rozpoznanie i skupienie się na
• Projektant aplikacji
korzystający z usług
oferowanych przez dostępne
biblioteki klas, wymagane
gromadzenie i rozeznanie w
usługach oferowanych przez
(często bardzo liczne) zbiory
dostępnych klas
dziedzinie problemu,
dostarczenie implementacji
ustalonego interfejsu i jej
„ukrycie” aby uŜytkownik
(konsument klas) miał dostęp
jedynie do niezbędnych
elementów, implementację
moŜna będzie bezpiecznie
zmodyfikować a ponadto słabo
rozeznany w dziedzinie
„konsument” nic nie zepsuje
rodzaj muru ceglanego oddzielającego twórcę
klasy od programisty-konsumenta
• public – dostęp dla kaŜdego
• protected – dostęp dla klasy pochodnej
• defualt – dostęp pakietowy - klasy z tego samego
pakietu (biblioteki) mają domyślny dostęp do składowych
klasy nieoznaczonych odpowiednim słowem kluczowym
2
Kompozycja-ponowne wykorzystanie
implementacji
Dziedziczenie
• Relacja typu „ma” „zawiera” („has-a”),
często niedoceniana w podręcznikach,
które skupiają się na dziedziczeniu,
poniŜej notacja UML-owa (teŜ jak BlueJ)
• MoŜliwe jest rozbudowanie i
wprowadzenie modyfikacji do istniejących
typów (klasa bazowa,nadklasa ... klasa
pochodna, podklasa...)
Mikrokontroler
Licznik
A singly rooted hierarchy
Wersje Javy
• Klasa Object wierzchołkiem dziedziczenia
wszystkich obiektów w Javie, wspólny
interfejs określony przez Object
• Np. String toString() kaŜdy obiekt „umie”
się przedstawić dostarczając znakowej
informacji o sobie. (tworząc nowe klasy
dostarczajmy rozsądnej implementacji tej
metody)
• 1.0
• 1.1
•
•
•
•
•
1.2
1.3
1.4
1.5
1.6
• „Java 1” ?
• Java 2
Windows, Linux, SunOS,
Mac
3
Edycje (profile)
•
•
•
•
J2SE http://java.sun.com/j2se/
J2EE http://java.sun.com/j2ee/index.jsp
J2ME http://java.sun.com/j2me/index.jsp
...
JIT
• Typowa implementacja JVM to emulator
działający w środowisku Windows, Unix, MacOS
etc., który interpretuje kod bajtowy
umieszczony w plikach „.class” co implikuje
gorszą efektywność wykonania programu w
stosunku do aplikacji natywnych.
• Obecne implementacje (Java HotSpot)
wykorzystują ideę JIT dokonując kompilacji “w
locie” i optymalizacji kodu bezpośrednio przed
wykonaniem.
Typy Danych
Manipulowanie obiektem
• Proste -
• Tylko pośrednio przez referencję
pojedyncza wartość określonego rozmiaru i
formatu (typ całkowity int 32 bity (uzupełnienie do 2),
char 16 bitów Unicode)
• Referencyjne
(Tablice, klasy i interfejsy)
W Javie niedopuszczalne jest bezpośrednie
wykorzystywanie i wykonywanie operacji na referencjach
(adresach) (jak np. w języku C), lecz wykorzystuje się nazwy
zmiennych (obiektów).
•
•
•
•
•
-analogia do
urządzenia i pilota sterującego (telewizor, okap
kuchenny) włączasz, zmieniasz kanał/szybkość wywiewu
za pomocą pilota)
String s = new String("asdf"); // s to pilot s.length()
String s; s.length() ; // ??? Sam pilot na niewiele się przyda ...
String s = "asdf"; s.length(); // teraz ok. ale to wyjątek !!!
Licznik licz = ??? „16,true, true” no!
Licznik licz = new Licznik(16, true, true); //utworzenie
obiektu typu Licznik i związanie z referencją licz
4
Literały
Typ
prosty
boolean
Size
Min
Max
—
—
—
Wrapper
type
Boolean
char
16-bit
Unicode 0
Unicode 216- 1
Character
byte
8-bit
-128
+127
Byte
Literal
Data Type
short
16-bit
-215
+215—1
Short
178
int
int
32-bit
-231
+231—1
Integer
8864L
long
64-bit
-263
+263—1
Long
float
32-bit
IEEE754
IEEE754
Float
double
64-bit
IEEE754
IEEE754
Double
void
—
—
—
Void
Zasięg (scope)
O zasięgu w Javie (podobnie jak w C) decydują nawiasy {}
{
int x = 12;
// Only x available
{
int q = 96;
// Both x & q available
}
// Only x available // q “out of scope”
}
Zmienna zdefiniowana wewnątrz bloku ograniczonego nawiasami {}
jest dostępna tylko do końca tego bloku
{ int x = 12;
{ int x = 96; // Illegal }
}
wartość (liczbowa, tekstowa, itp.) wpisana bezpośrednio w kod programu
Literal
Data Type
26.77e3
double
long
'c'
char
37.266
double
true
boolean
37.266f
float
false
boolean
Zasięg obiektów
{
String s = new String("a string");
} // End of scope
Referencja s do obiektu typu String znika wraz z
końcem zasięgu, ale obiekt jest dalej
przechowywany w pamięci! I pozostanie w niej tak
długo jak potrzeba.
>>W Javie nie ma potrzeby troszczenia się o
usuwanie zbędnych obiektów!<<
5
Odśmiecacz
Gospodarka pamięcią
• W języku Java nie ma koncepcji destruktora. W zamian
wprowadzono tzw. „odśmiecacz” (garbage collector),
który zajmuje się odzyskiwaniem pamięci po
niepotrzebnych obiektach (ale tylko tych zaalokowanych
przez operator new).
• Bezpośrednio przed usunięciem obiektu z pamięci
odśmiecacz wywołuje metodę finalize() na rzecz obiektu
co pozwala na wykonanie czynności porządkujących.
• Trzeba jednak pamiętać, Ŝe odśmiecacz działa
asynchronicznie (moŜna wymusić jego wykonanie
System.gc()) i moŜe w ogóle nie zadziałać w trakcie
działania programu (cała pamięć zostania en masse
zwrócona po jego zakończeniu).
• W Javie wszystkie obiekty alokowane są na
stercie (heap) co jest mniej efektywne niŜ
korzystanie ze stosu. Z tego powodu w
implementacjach maszyny wirtualnej Java
stosowane są specjalne algorytmy alokacji
(rodzaj pasa transmisyjnego) co daje
efektywność zbliŜoną do stosu. Przy
wyczerpywaniu się zasobów sterty do gry
wkracza odśmiecacz, który realokuje obiekty
„cofa i włącza taśmociąg ponownie”.
Tworzenie nowych typów
Metody, argumenty, zwracane
wartości
• class ATypeName { /* Class body goes here */ }
• „type ATypeName { /* Type body goes here */ }”
• ATypeName a = new ATypeName(); // possible?
class DataOnly {
int i;
float f;
boolean b;
}
DataOnly d = new DataOnly();
d.i = 47;
• returnType methodName( /* Argument list */ )
{ /* Method body */ }
Nazwa metody i lista argumentów
jednoznacznie identyfikuje metodę.
Metody są częścią klasy (tylko
wewnątrz klasy)
Wywoływanie metod:
objectName.methodName(arg1, arg2, arg3);
6
Overloading -PrzeciąŜanie
Konstruktor domyślny
• int m(int a, float b) {...}
• int m(float a, char b) {...}
• int m(double c) {...}
• Ok.
• int m(int a, float b) {...}
• float m(int a, float b)
{...}
• ??? Why not?
• float x=m(10, 3.2F);
• Jeśli zdefiniujemy klasę nie umieszczając
w niej konstruktora wówczas kompilator
automatycznie umieści w niej konstruktor
bezargumentowy zwany takŜe
konstruktorem domyślnym (default
constructor).
• Jeśli jednak zdefiniujemy chociaŜ jeden
konstruktor kompilator nie dodaje
konstruktora domyślnego!
• m(10, 3.2F); // ??? side
//effect
Konstruktor domyślny
Słowo kluczowe this
• class Hat {
Hat(int i) {}
Hat(double d) {}
}
Teraz
• new Hat(); // ???
jest niepoprawne poniewaŜ kompilator nie
znajdzie odpowiedniego konstruktora!
• class Banana { void f(int i) { /* ... */ } }
• Banana a = new Banana(), b = new Banana();
• a.f(1); b.f(2);
• W rzeczywistości to wywołanie ma postać:
Banana.f(a,1);
Banana.f(b,2);
• To znaczy pierwszym „ukrytym” parametrem
metody jest referencja do obiektu!
7
this c.d.
this w konstruktorze
• Jeśli wewnątrz metody potrzebujemy referencji
do tego obiektu a nie mamy przecieŜ
identyfikatora bo jest ukryty to wykorzystujemy
słowo kluczowe this, które jest właśnie
synonimem referencji do bieŜącego (tego)
obiektu.
• Jeśli wewnątrz metody chcemy wywołać inną
metodę obiektu to moŜna to zapisać:
• this.innaMetoda(); ale nie jest to konieczne!
Kompilator realizuje to automatycznie.
• Gdy definiujemy szereg konstruktorów w
klasie ( typowe), bardzo często
wywołujemy jeden z drugiego aby uniknąć
powielania kodu (lenistwo!). Wewnątrz
konstruktora zapis
• this(arg, arg, ...)
jest odwołaniem do innego konstruktora,
którego parametry odpowiadają liście
argumentów. Takie wywołanie musi
wystąpić na początku i tylko raz!
Przysłonięcie
Metody statyczne
• Drugim typowym zastosowaniem słowa
kluczowego this jest sytuacja, w której parametr
metody i pole składowe klasy są identyczne.
Następuje wówczas przysłonięcie pola
składowego przez ten parametr, this pozwala na
odniesienie do przysłoniętego pola składowego.
• Niejawne przekazanie referencji do obiektu jako
pierwszego parametru metody
reprezentowanego przez słowo kluczowe this nie
ma miejsca w przypadku metod statycznych!
(które są związane z klasą). Z wnętrza metod
statycznych nie moŜna wywoływać metod
niestatycznych, chociaŜ odwrotna operacja jest
moŜliwa. Metody statyczne moŜna wywoływać
bez konieczności uprzedniego kreowania
obiektów! Jest to zresztą zasadniczy sens
istnienia metod statycznych. Przykłady:
• Math.sin(); System.out.println();
int stan;
//...
void setStan(int stan) {
this.stan = stan; } //is it really good style?
• Czy moŜna wywołać konstruktor z innej metody
(nie konstruktora)? NIE!
8
Metody statyczne
Konflikty nazw
• Statyczne metody są odpowiednikami funkcji globalnych
języka C, które w języku Java nie występują! MoŜna
napotkać argumentację, Ŝe metody statyczne nie są
obiektowo zorientowane, za ich stosowaniem
przemawiają względy praktyczne, stąd w całym API Javy
istnieją setki klas z metodami statycznymi (niektóre tzw.
utility class posiadają wyłącznie metody statyczne).
Znacznie wygodniej obliczyć cosinus kąta alfa za pomocą:
double co = Math.cos (alfa) ;
niŜ
Math m = new Math();
double co = m.cos (alfa) ;
• W wielomodułowych programach opracowywanych przez
zespoły programistów łatwo moŜe dochodzić do
konfliktów nazw (identyczne nazwy klas). Identyczne
nazwy mogą takŜe znaleźć się w wykorzystywanych
bibliotekach. Twórcy języka Java zaproponowali
konwencję tworzenia nazw bibliotek odwołujących się do
DNS-owej przestrzeni nazw co zapewnia jednoznaczność
gdyŜ uzyskujemy hierarchiczną wielopoziomową
przestrzeń nazw.
• pl.wroc.pwr.kmeif.mylibrary (odwrócona kolejność!)
• Ale pojawia się problem odszukania (lokalizacji)
właściwej klasy
Importowanie klas/pakietów
„HelloWorld” Program
• Klasa jest zdefiniowana w tym samym pliku – nie ma problemu, nie
ma potrzeby uŜywania „forward”
• Jeśli potrzebna klasa znajduje się w innej bibliotece wskazujemy jej
lokalizację za pomocą deklaracji importu:
import java.util.ArrayList; // poza klasą!!!
Możemy także zaimportować całą bibliotekę (wszystkie klasy z tej
biblioteki):
import java.util.*;
// częściej w praktyce stosowane
Uwaga: standardowe biblioteki Javy (java API) nie mają prefiksu domeny
(com.sun...)
Nie trzeba importować biblioteki (pakietu) java.lang! (Object, System
klasy opakowujące, String, Thread ...)
http://156.17.45.3/~janpek/javaAPI/index.html
• // HelloDate.java
import java.util.*;
public class HelloDate {
public static void main(String[] args) {
System.out.println("Hello, it's: ");
System.out.println(new Date());
}
}
9
Komentarze
Kompilacja
/* This is a comment
* that continues
* across lines */
// This is a one-line comment
Komentarze dokumentacyjne związane z narzędziem
javadoc
• javac HelloDate.java
Klasa HelloDate (zawierająca metodą main)
musi być zapisana w pliku o odpowiedniej
nazwie (HelloDate.java)
/** A class comment */
Inicjalizacja
Inicjalizacja składowych klasy
• Zmienne lokalne metod muszą być
zainicjalizowane inaczej kompilator
zasygnalizuje błąd!
• void f() {
int i;
•
•
i++; // Error -- i not initialized
• }
• ChociaŜ kompilator mógłby domyślnie
inicjalizować je przyjęto załoŜenie, Ŝe brak
takiej inicjalizacji jest częściej symptomem
błędu niŜ zamierzonym efektem.
• W przeciwieństwie do zmiennych lokalnych
jawne inicjalizowanie zmiennych
składowych klasy nie jest konieczne,
jednak nie pozostawia się ich wartości
przypadkowi i inicjalizuje domyślnie
(wartości zerowe i false dla typów
prostych i null dla typów obiektowych).
„null” jest słowem kluczowym języka Java
10
Domyślne inicjalizacje
Primitive type Default
boolean
false
char
‘\u0000’ (null)
byte
(byte)0
short
(short)0
int
long
float
double
0
0L
0.0f
0.0d
Jednoczesna inicjalizacja wartości z
deklaracją zmiennej
class InitialValues {
boolean b = true;
char c = 'x';
byte b = 47;
short s = 0xff;
int i = 999;
long l = 1L;
float f = 3.14f;
double d = 3.14159;
Depth d = new Depth();
// ale nie tak!
Depth d ; d= new Depth();
int i = f(); // ale tak jest ok, metodę moŜna wywołać
Inicjalizacja za pomocą konstruktora
Sekcja static
• class Counter {
• int state = 255;
• public Counter(){
•
state = 1;
•
}
• // . . .
• Trzeba pamiętać, Ŝe najpierw inicjalizowane są
wartości zmiennych w kolejności ich
występowania dopiero później wywoływany jest
konstruktor (najpierw 255 potem 1).
• class Spoon {
• static int i;
• static { //składnia podobna do metody
•
i = 47;
• }
• Blok statyczny wykonywany jest tylko raz w
momencie kreowania (pierwszego) obiektu lub
przy pierwszym dostępie do składowej statycznej
tej klasy nawet jeśli nigdy nie będzie kreowany
Ŝaden obiekt.
11