Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych

Podobne prezentacje


Prezentacja na temat: "Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych"— Zapis prezentacji:

1 Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
(c) Krzysztof Barteczko 2014

2 to klasa zdefiniowana wewnątrz innej klasy.
Klasy wewnętrzne - definicja Klasa wewnętrzna to klasa zdefiniowana wewnątrz innej klasy. class A {      class B {      ....      } } Klasa B jest klasą wewnętrzną w klasie A. Klasa A jest klasą otaczającą klasy B. (c) Krzysztof Barteczko 2014

3 Klasa wewnętrzna a otaczająca
(c) Krzysztof Barteczko 2014

4 Właściwości klas wewnętrznych
(c) Krzysztof Barteczko 2014

5 Po co są klasy wewnętrzne?
(c) Krzysztof Barteczko 2014

6 (c) Krzysztof Barteczko 2014
Przykład (c) Krzysztof Barteczko 2014

7 (c) Krzysztof Barteczko 2014
Kod public class Car extends Vehicle { // ... private class FuelConsume implements ActionListener { @Override public void actionPerformed(ActionEvent e) { fuel -= 1; // odwolanie do pryw. składowej klasy otaczającej if (fuel == 0) stop(); } private Timer fuelTimer = new Timer(1000, new FuelConsume()); public Car start() { if (getState() == MOVING) return this; // nie można użyć start 2 razy pod rząd! if (fuel > 0) { super.start(); if (getState() == MOVING) // tylko jeśli udało się wystartować pojazd! fuelTimer.start(); // --- start Timera else error("Brak paliwa"); return this; public Car stop() { fuelTimer.stop(); super.stop(); public void crash(Vehicle v) { this.fuelTimer.stop(); if (v instanceof Car) ((Car) v).fuelTimer.stop(); super.crash(v); (c) Krzysztof Barteczko 2014

8 (c) Krzysztof Barteczko 2014
Test (c) Krzysztof Barteczko 2014

9 Odwołania do klasy wewnętrznej
Odwołanie do widocznej (np. publicznej) klasy wewnętrznej: NazwaKlasyOtaczającej.NazwaKlasyWewnętrznej Tworzenie obiektu niestatycznej klasy wewnętrznej wymaga zawsze istnienia obiektu klasy otaczającej. (c) Krzysztof Barteczko 2014

10 Anonimowe klasy wewnętrzne
(c) Krzysztof Barteczko 2014

11 Schematyczny przykład
Record jakisRekord; //.... db.add(jakisRekord); (c) Krzysztof Barteczko 2014

12 Anonimowy FuelConsumer
(c) Krzysztof Barteczko 2014

13 (c) Krzysztof Barteczko 2014
Uproszczenie Po co nam zmienna fuelConsumer? Przecież wszędzie tam, gdzie może wystąpić referencja może wystąpić wyrażenie new. Może zatem wystąpić jako drugi argument wyrażenia new, tworzacego timer. private Timer fuelTimer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { fuel -= 1; if (fuel == 0) stop(); } }); (c) Krzysztof Barteczko 2014

14 Uwagi nt anonimowych klas wewnętrznych
(c) Krzysztof Barteczko 2014

15 Lokalne klasy wenętrzne
(c) Krzysztof Barteczko 2014

16 Java7 Przykład: wyszukiwanie plików
Wobec katalogu można użyć metody listFiles z klasy File, która zwraca tablicę obiektów plikowych w nim zawartych. Używając metody listFiles z argumentem typu FileFilter możemy określić kryteria filtrowania wyniku według właściwości obiektów plikowych (np. otrzymać tylko listę plików o rozszerzeniu .java lub zmodyfikowanych po jakiejś dacie). FileFilter jest interfejsem, w którym zawarto jedną metodę boolean accept(File file). File dir = new File(...); Calendar c = Calendar.getInstance(); c.set(2013, 7, 22, 0, 0); final long time = c.getTimeInMillis(); File[] files = dir.listFiles( new FileFilter() { public boolean accept(File file) { return file.isFile() && file.getName().endsWith(".java") && file.lastModified() >= time; } }); Java7 (c) Krzysztof Barteczko 2014

17 Java7 Parametry to też zmienne lokalne
static File[] getFiles(String fromDir, final String ext, String afterDate) throws ParseException { final long time = new SimpleDateFormat("yyyy-MM-dd") .parse(afterDate) .getTime(); File[] files = new File(fromDir).listFiles( new FileFilter() { @Override public boolean accept(File f) { return f.isFile() && f.getName().endsWith(ext) && f.lastModified() >= time; } }); return files; (c) Krzysztof Barteczko 2014

18 Java8 Zmienne efektywnie finalne
W Javie w wersji 8 wprowadzono wygodne pojęcie zmiennej efektywnie finalnej (effectively final). Jest to taka zmienna, co do której kompilator może stwierdzić, że nie zmienia ona swoich wartości (np. nie występuje z lewej strony przypisań). Dzięki temu osłabiono wymaganie na dostęp do zmiennych lokalnych z anonimowych klas wewnętrznych: takie zmienne nie muszą być już deklarowane ze specyfikatorem final, ale muszą być efektywnie finalne. static File[] getFiles(String fromDir, String ext, String afterDate) throws ParseException { long time = // ... File[] files = new File(fromDir).listFiles( new FileFilter() { @Override public boolean accept(File f) { return f.isFile() && f.getName().endsWith(ext) && f.lastModified() >= time; } }); return files; Java8 (c) Krzysztof Barteczko 2014

19 Praktyczna użyteczność interfejsów i klas wewnętrznych
interfejsy kolekcyjne iterowalne obiekty niekolekcyjne wizytowanie drzew katalogowych (c) Krzysztof Barteczko 2014

20 w kategoriach interfejsów, a nie konkretnych klas
Interfejsy kolekcyjne Klasy kolekcyjne w Javie implementują  odpowiednie interfejsy. Na przykład: klasy ArrayList i LinkedList - interfejs List, klasy HashSet, LinkedHashSet i TreeSet - interfejs Set. Interfejsy określają dostępne operacje na wyznaczanych przez nie strukturach danych, a wybór implementacji zależy od potrzeb naszego programu (rózne implementacje mają rózne właściwości). Gdy nasz program tworzy konkretne obiekty klas kolekcyjnych, to zawsze musimy dokonać takiego wyboru. Ale ważną rzeczą jest, by wszelkie inne działania na kolekcjach wykonywać w kategoriach interfejsów, a nie konkretnych klas  Zwiększa to uniwersalność kodu. (c) Krzysztof Barteczko 2014

21 (c) Krzysztof Barteczko 2014
Przykład (c) Krzysztof Barteczko 2014

22 (c) Krzysztof Barteczko 2014
Interfejs Iterable (c) Krzysztof Barteczko 2014

23 Iterowalne obiekty niekolekcyjne
(c) Krzysztof Barteczko 2014

24 (c) Krzysztof Barteczko 2014
Realizacja class FromTo implements Iterable<Calendar> { private Calendar from = Calendar.getInstance(), to = Calendar.getInstance(); public FromTo(String fromString, String toString) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); try { from.setTime(df.parse(fromString)); to.setTime(df.parse(toString)); } catch (ParseException exc) { throw new IllegalArgumentException(exc.getMessage()); } public Iterator<Calendar> iterator() { return new Iterator<Calendar>() { Calendar current = Calendar.getInstance(), next = Calendar.getInstance(); { current.setTime(from.getTime()); current.add(Calendar.DATE, -1); public boolean hasNext() { next.setTime(current.getTime()); next.add(Calendar.DATE, 1); return next.compareTo(to) <= 0; public Calendar next() { if (!hasNext()) throw new NoSuchElementException(); current.add(Calendar.DATE, 1); return current; }; W Javie 8 interfejs Iterator zawiera domyślną metodę remove(), więc nie trzeba jej implementować. (c) Krzysztof Barteczko 2014

25 Wizytowanie drzew katalogowych
W klasie java.nio.file.Files znajdziemy użyteczną metodę statyczną: Path walkFileTree(Path startDir, FileVisitor visitor) która pozwala na rekurencyjne przeglądanie katalogów (poczynając od katalogu startDir) i wykonywanie operacji na ich elementach (plikach i podkatalogach). (c) Krzysztof Barteczko 2014

26 Metody interfejsu FileVisitor
(c) Krzysztof Barteczko 2014

27 (c) Krzysztof Barteczko 2014
Wyniki wizytowania (c) Krzysztof Barteczko 2014

28 Przykład wizytowania drzewa katalogowego
public class CountLines { private long count = 0; private PathMatcher matcher; private Path startDir; public CountLines(String startDir) { this.startDir = Paths.get(startDir); } public long of(String glob) throws IOException { matcher = FileSystems.getDefault().getPathMatcher("glob:*.java"); Files.walkFileTree(startDir, new SimpleFileVisitor<Path>() { public FileVisitResult visitFile(Path file, BasicFileAttributes a) { if (matcher.matches(file.getFileName())) { try { count += Files.readAllLines(file, Charset.defaultCharset()).size(); } catch (IOException exc) { System.out.println(exc); return FileVisitResult.CONTINUE; }); return count; public static void main(String[] args) throws IOException { long count = new CountLines("..").of("*.java"); System.out.println("Lines count: " + count); PathMatcher – regex lub glob SimpleFileVisitor daje standard, umozliwia wybór metod (c) Krzysztof Barteczko 2014

29 Pojęcie o lambda-wyrażeniach
(c) Krzysztof Barteczko 2014

30 (c) Krzysztof Barteczko 2014
Lambda – przykład 1 (c) Krzysztof Barteczko 2014

31 (c) Krzysztof Barteczko 2014
Lambda – przykład 2 (c) Krzysztof Barteczko 2014


Pobierz ppt "Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych"

Podobne prezentacje


Reklamy Google