• Nie Znaleziono Wyników

1 OOP Interfejs obiektu Programowanie w Java Charakterystyka językaSmalltalk

N/A
N/A
Protected

Academic year: 2021

Share "1 OOP Interfejs obiektu Programowanie w Java Charakterystyka językaSmalltalk"

Copied!
11
0
0

Pełen tekst

(1)

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

Charakterystyka języka Smalltalk

1. Everything is an object. (wyjątek typy proste) 2. 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

• 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.

Interfejs obiektu

• 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)

(2)

Wykonaj polecenie twoja sprawa jak

Light lt =newLight(); // 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

• Kreator klas

• Rozpoznanie i skupienie się na 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

• Konsument klas

• 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

Specyfikatory dostępu

• private – dostęp tylko dla projektanta klasy, 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

(3)

Kompozycja-ponowne wykorzystanie implementacji

• 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)

Mikrokontroler Licznik

Dziedziczenie

• MoŜliwe jest rozbudowanie i

wprowadzenie modyfikacji do istniejących typów (klasa bazowa,nadklasa ... klasa pochodna, podklasa...)

A singly rooted hierarchy

• 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)

Wersje Javy

• 1.0

• 1.1

• 1.2

• 1.3

• 1.4

• 1.5

• 1.6

• „Java 1” ?

• Java 2

Windows, Linux, SunOS,

Mac

(4)

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

• Proste -

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).

Manipulowanie obiektem

• Tylko pośrednio przez referencję

-analogia do urządzenia i pilota sterującego (telewizor, okap kuchenny) włączasz, zmieniasz kanał/szybkość wywiewu za pomocą pilota)

• String s =newString("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

(5)

Typ prosty

Size Min Max Wrapper

type

boolean — — — Boolean

char 16-bit Unicode 0 Unicode 216- 1 Character

byte 8-bit -128 +127 Byte

short 16-bit -215 +215—1 Short

int 32-bit -231 +231—1 Integer

long 64-bit -263 +263—1 Long

float 32-bit IEEE754 IEEE754 Float double 64-bit IEEE754 IEEE754 Double

void — — — Void

Literały

Literal Data Type 26.77e3 double

' c ' char

true boolean

false boolean Literal Data Type

178 int

8864L long

37.266 double

37.266f float

wartość (liczbowa, tekstowa, itp.) wpisana bezpośrednio w kod programu

Zasięg (scope)

O zasięgu w Javie (podobnie jak w C) decydują nawiasy {}

{ intx = 12;

// Only x available { intq = 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 {intx = 12;

{ intx = 96; // Illegal} }

Zasięg obiektów

{

String s =newString("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!<<

(6)

Odśmiecacz

• 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).

Gospodarka pamięcią

• 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

• class

ATypeName { /* Class body goes here */ }

• „type

ATypeName { /* Type body goes here */ }”

• ATypeName a =

new

ATypeName(); // possible?

classDataOnly { inti;

floatf;

booleanb;

}

DataOnly d =newDataOnly();

d.i = 47;

Metody, argumenty, zwracane wartości

• 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);

(7)

Overloading -PrzeciąŜanie

• int m(int a, float b) {...}

• int m(float a, char b) {...}

• int m(double c) {...}

• int m(int a, float b) {...}

• float m(int a, float b) {...}

• Ok.

• ??? Why not?

• float x=m(10, 3.2F);

• m(10, 3.2F); // ??? side

//

effect

Konstruktor domyślny

• 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!

Konstruktor domyślny

• class Hat { Hat(int i) {}

Hat(double d) {}

} Teraz

• new Hat(); // ???

jest niepoprawne poniewaŜ kompilator nie znajdzie odpowiedniego konstruktora!

Słowo kluczowe this

• 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!

(8)

this c.d.

• 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.

this w konstruktorze

• 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

• 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.

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!

Metody statyczne

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

(9)

Metody statyczne

• 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) ;

Konflikty nazw

• 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

• 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:

importjava.util.ArrayList; // poza klasą!!!

Możemy także zaimportować całą bibliotekę (wszystkie klasy z tej biblioteki):

importjava.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

„HelloWorld” Program

• // 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());

}

}

(10)

Komentarze

/* This is a comment

* that continues

* across lines */

// This is a one-line comment

Komentarze dokumentacyjne związane z narzędziem javadoc

/** A class comment */

Kompilacja

• javac HelloDate.java

Klasa HelloDate (zawierająca metodą main) musi być zapisana w pliku o odpowiedniej nazwie (HelloDate.java)

Inicjalizacja

• 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.

Inicjalizacja składowych klasy

• 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

(11)

Domyślne inicjalizacje

Primitive type Default

boolean false

char ‘\u0000’ (null)

byte (byte)0

short (short)0

int 0

long 0L

float 0.0f

double 0.0d

Jednoczesna inicjalizacja wartości z deklaracją zmiennej

classInitialValues { booleanb = true;

charc = 'x';

byteb = 47;

shorts = 0xff;

inti = 999;

longl = 1L;

floatf = 3.14f;

doubled = 3.14159;

Depth d = newDepth();

Depth d ; d= newDepth(); // ale nie tak!

inti = f(); // ale tak jest ok, metodę moŜna wywołać

Inicjalizacja za pomocą konstruktora

• 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).

Sekcja static

• classSpoon {

• 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.

Cytaty

Powiązane dokumenty

lista składowych klasy - deklaruje składowe klasy, czyli dane i.. b) Deklaracja składowych wewnątrz klasy. C) Definicja składowych na zewnątrz klasy – kod metod występuje w jednym

• Każdy organ nadzorczy, przewodniczący Europejskiej Rady Ochrony Danych lub Komisja mogą wystąpić o przeanalizowanie przez Europejską Radę Ochrony Danych w celu wydania

§ 3. Organ, którego działanie, bezczynność lub przewlekłe prowadzenie postępowania zaskarżono, może w zakresie swojej właściwości uwzględnić skargę w

public static void main (String[] args) {} ¡– główna metoda;.. import

Rysunek: Import bibliotek i klasa Random... Rysunek: Import wielu

Przykład z wątkami i JSON Excel i obsługa plików xls Generowanie i odczyt plików pdf. Generowanie skryptów do aplikacji zewnętrznych Zagadnienia

dwie jedna z liczb dodatnia, druga ujemna: odejmnowanie drugiej liczby od pierwszej.. dwie liczby ujemne: program wypisuje komunikat:

[r]