Računalništvo 1 (PRA)

lekcije / Dedovanje, prekrivanje, vmesniki in izjeme

Objektno programiranje 2

V tej lekciji bom spoznali osnovne koncepte objektnega programiranja v Javi:

Objektne in statične metode in komponente

Vemo že, da vsak objekt sestoji iz objektnih komponent in objektnih metod. Poleg tega obstajajo v Javi še statične metode in statične komponente. (Statične metode se v neobjektnih programskih jezikih imenujejo "funkcije" ali "procedure", statične komponente pa se imenujejo "globalne spremenljivke".)
Pojasnimo razliko med statičnimi in objektnimi komponentami. Obravnavajmo razred Foo:
1
2
3
4
5
6
7
8
public class Foo {
    static int x = 12;
    int y;

    public Foo(int z) {
       this.y = z;
    }
}
Razred ima eno statično komponento x in eno objektno (nestatično) komponento y. Kako razumeti vsako od njih? Velja načelo:
Statične komponente so vsebovane v razredu, objektne komponente pa v objektih.
Vsak objekt vsebuje svojo kopijo objektnih komponent, vsaka statična komponenta pa vedno obstaja v eni sami kopiji.
Denimo, da izvedemo naslednja ukaza:
1
2
Foo t1 = new Foo(42);
Foo t2 = new Foo(30);
Potem imamo dva objekta, zato imamo dve kopiji komponente y, po eno v vsakem objektu. Ker je komponenta x statična, vedno obstaja v eni sami kopiji, tudi če nimamo nobenih objektov razreda Foo: Shematski prikaz objektov t1 in t2
Naloga 1: Objektni zajci
[rešitev]
Kako vemo, ali naj bo komponenta statična ali objektna? Statične komponente so tiste, ki so skupne za celoten program. Na primer, v prejšnji vaji je min_masa statična komponenta, ker je najmanjša dovoljena masa zajca število, ki je skupno za ves program (za vse zajce). Komponenta masa je objektna, ker ima vsak zajec svojo maso.
Kaj pa razlika med statičnimi in objektnimi metodami? Najpomembnejša razlika je tale:
Statično metodo bla() v razredu Foo lahko vedno izvedemo z ukazom Foo.bla(). Znotraj statične metode objekt this ni definiran, ker se statična metode ne kliče na objektu.
Objektno metodo hej() v razredu Foo lahko izvedemo, če imamo neki objekt x razreda Foo, z ukazom x.hej(). Znotraj metode hej() označuje this objekt, na katerem je metoda poklicana.
Na primer, če imamo razred
1
2
3
4
5
6
7
8
9
10
11
12
public class Foo {
    static int x = 12;
    int y;

    public Foo(int z) {
       this.y = z;
    }

    static int f(int a) { return x + a; }

    int g(int a) { return this.y + x + a; }
}
potem ima statična metoda f dostop do komponente x. Dostopa do komponente y nima, saj znotraj statične metode ne moremo pisati this.y. Objektna metoda g pa ima dostop do komponente this.y, kjer je this objekt, na katerem je metoda g klicana. Na primer:
1
2
3
4
5
6
int p = Foo.f(7);     // p == 12 + 7 == 19
Foo.x = -3;
int q = Foo.f(5);     // q == -3 + 5 == 2
Foo t = new Foo(100);
Foo s = new Foo(200);
int r = t.g(50);      // r == 100 + (-3) + 50 == 147
Naloga 2
[rešitev]

Dedovanje

Dedovanje je metoda objektnega programiranja, s katero organiziramo in povežemo razrede, ki sestavljajo program. Ogledali si bomo klasični primer dedovanja geometrijskih likov.
Denimo, da pišemo program, v katerem imamo opravka z geometrijskimi liki, kot so trikotnik, krog, kvadrat, ipd. Za vsak lik poznamo njegovo lego (x, y) v ravnini. Denimo, da mora program znati translirati lik za dani vektor in izračunati njegovo ploščino. Vprašanje je, kako bi to naprogramirali. (Pravi program bi moral znati dosti več, a ti dve metodi bosta zadostovali za naš preprost primer.)
Za vsak lik, ki ga program pozna, napravimo svoj razred. Denimo, da želimo delati s trikotniki, krogi in kvadrati. Torej bomo definirali tri razrede Trikotnik, Krog in Kvadrat.
Po drugi strani bi bilo dobro definirati splošen razred Lik, ki bi združeval vse like, s katerimi zna program delati. Z diagramom bi to prikazali takole:
Dedovanje likov
Kar je vsem likom skupnega, bi dali v razred Lik, kar pa je za vsak lik specifično, bi spadalo v pripadajoči razred. Na primer, pozicija na ravnini je vsem likom skupna, zato je to del razreda Lik. Krog ima polmer r, kvadrat ima dolžino stranice a, trikotnik pa ima pozicije oglišč. To so podatki, ki spadajo v vsak posamezni razred.
Pravimo, da so razredi Trikotnik, Krog in Kvadratpodrazredi razreda Lik, ali da je razred Lik njihov nadrazred. V Javi povemo, da je en razred podrazred nekega drugega razreda z določilom extends:
public class Trikotnik extends Lik {
   ...
}
Besedica "extends" pomeni "razširi" in je uporabljena zato, ker razred Trikotnik vsebuje vse komponente in metode, ki jih vsebuje razred Lik (in še dodatne komponente in metode, ki jih razred Lik morda nima).
Razrede Lik, Trikotnik, Krog in Kvadrat bi napisali takole:
Lik.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Lik {
    double x;
    double y;

    public Lik(double x, double y) {
	this.x = x;
	this.y = y;
    }

    public void transliraj(double dx, double dy) {
       x = x + dx;
       y = y + dy;
    }

    public abstract double ploscina();
}
Krog.java
1
2
3
4
5
6
7
8
9
10
11
12
public class Krog extends Lik {
    double r; // polmer

    public Krog(double x, double y, double r) {
	super(x, y);
	this.r = r;
    }

    public double ploscina() {
       return Math.PI * r * r;
    }
}
Kvadrat.java
1
2
3
4
5
6
7
8
9
10
11
12
public class Kvadrat extends Lik {
    double a; // dolzina stranice

    public Kvadrat(double x, double y, double a) {
	super(x, y);
	this.a = a;
    }

    public double ploscina() {
       return a * a;
    }
}
Trikotnik.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Trikotnik extends Lik {
    double x2, y2; // drugo oglisce
    double x3, y3; // tretje oglisce

    Trikotnik(double x, double y,
		     double x2, double y2,
		     double x3, double y3) {
	super(x, y);
	this.x2 = x2; this.y2 = y2;
	this.x3 = x3; this.y3 = y3;
    }

    public double ploscina() {
	return 0.5 * Math.abs(x3*y - x2*y + x*y2 -  x3*y2 - x*y3 + x2*y3);
    }
}
Oglejmo si vsakega od razredov bolj natačno. Vsak razred vsebuje po en konstruktor. V konstruktorjih za podrazrede vidimo klic super(x, y), s katerim pokličemo konstruktor nadrazreda Lik.
Razred Lik vsebuje komponenti double x, double y in objektno metodo void transliraj(double dx, double dy). Razred Lik vsebuje tudi abstraktno deklaracijo metode double ploscina(). S to deklaracijo povemo, da mora vsak podrazred razreda Lik definirati tako metodo. Razred Lik ne vsebuje metode double ploscina(), saj za splošni lik ne moremo definirati metode, ki izračuna njegovo ploščino. Zato pravimo, da je metode ploščina samo abstraktno deklarirana. Kadar je v razredu deklarirana abstraktna metoda, s tem tudi celoten razred postane abstrakten. Povzemimo:
public abstract class A {
  ...

  abstract int f(int x);

  ...
}
Vsak podrazred razreda A mora vsebovati metodo int f(int x). Razred A take metode ne vsebuje.
Razred A je abstrakten, ker je v njem deklarirana abstraktna metoda.
Ker je razred Krog definiran z določilom "extends Lik", vsebuje vse komponente, ki jih vsebuje razred Lik. Torej vsebuje tri komponente, double x, double y in double r, ter dve metodi, void transliraj(double dx, double dy) in double ploscina().
Razred Kvadrat vsebuje tri komponente, double x, double y in double a, ter dve metodi, void transliraj(double dx, double dy) in double ploscina().
Razred Trikotnik pa vsebuje šest komponent, double x, double y, double x2, double y2, double x3, double y3, ter dve metodi, void transliraj(double dx, double dy) in double ploscina().
Zapomnimo si, kako deluje določilo extends:
class A extends B {
  ...
}
  1. Razred Apodeduje komponente in metode od razreda B.
  2. Objekti razreda A so hkrati tudi objekti razreda B.
Krogi, kvadrati in trikotniki so liki. Uporabljamo jih takole:
1
2
3
4
5
Lik kr = new Krog(2.0, 3.0, 1.0);
Lik kv = new Kvadrat(0.0, 2.0, 7.0);
kr.transliraj(-2.0, 3.0);
double p = kr.ploscina();
double q = kv.ploscina();
Naloga 3
[rešitev]
Naloga 4: Barvni liki
Lik.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.awt.Color;
import java.awt.Graphics;

public abstract class Lik {
    double x, y;
    Color barva;

    public Lik(double x, double y) {
	this.x = x;
	this.y = y;
	this.barva = Color.black;
    }

    public Lik(double x, double y, Color c) {
	this.x = x;
	this.y = y;
	this.barva = c;
    }

    public void transliraj(double dx, double dy) {
       x = x + dx;
       y = y + dy;
    }

    public abstract double ploscina();

    public abstract void narisi(Graphics g);
}
Krog.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.awt.*;

public class Krog extends Lik {
    double r; // polmer

    public Krog(double x, double y, double r) {
	super(x, y);
	this.r = r;
    }

    public Krog(double x, double y, double r, Color c) {
	super(x, y, c);
	this.r = r;
    }

    public double ploscina() {
       return Math.PI * r * r;
    }

    public void narisi(Graphics g) {
	g.setColor(this.barva);
	g.fillOval((int)(this.x - this.r), (int)(this.y - this.r), (int)(2*r), (int)(2*r));
    }
}
Nato uporabimo razreda Okno.java in Slika.java za risanje slik (kako delujeta, na tem mestu ne bomo razlagali) takole:
> Okno w = new Okno();
> w.prikazi();
> w.dodaj(new Krog(100, 100, 80, Color.red);
  • Sestavi tudi podrazrede za kvadrat, trikotnik in pravokotnik.
  • Sestavi podrazred KvadratNagnjen razreda Kvadrat, ki predstavlja zasukan kvadrat.
  • Nariši lepo sliko!

Prekrivanje

Denimo, da imamo razred Foo in podrazred Qux, ki sta definirana takole:
Foo.java
1
2
3
4
5
6
7
8
9
10
11
12
public class Foo {
    int x;

    public Foo(int u) { this.x = u; }

    public int bla() {
	return this.x;

	Foo a = new Foo(42);
	Foo b = this(12);
    }
}
Qux.java
1
2
3
4
5
6
7
8
9
10
11
12
public class Qux extends Foo {
    int y;

    public Qux(int u, int v) {
	super(u);
	this.y = v;
    }

    public int bla() {
	return super.bla() + this.y;
    }
}
Metoda bla je definirana v razredu Foo. Ker razred Qux deduje od Foo, podeduje tudi metodo bla. Vendar pa Qux definira tudi svojo lastno metodo bla, ki prekrije dedovano metodo bla. Do prekrite metode lahko znotraj razreda Qux dostopamo z super.bla(). Besedica super pomeni, da se sklicujemo na nadrazred (angl. "superclass").
Primer:
1
2
3
4
Foo a = new Foo(10);   // a.x == 10
Foo b = new Qux(5, 7); // b.x == 5, b.y == 7
int p = a.bla();       // p == 10
int q = b.bla();       // q == 5 + 7 = 12
Naloga 5
[rešitev]

Določila public, private in protected

Ko definiramo razred vedno napišemo public class ... in ko definiramo metodo, običajno uporabimo določilo public. Poleg določila public pozna Java še določili private in protected.
Za komponento ali metodo veljajo naslednja pravila o dostopu:
public
Dostop imajo vsi razredi.
private
Dostop ima samo razred, v katerem je metoda ali komponenta definirana.
protected
Dostop imajo vsi razredi, ki so v istem paketu. O paketih še nismo govorili in letos tudi ne bomo. Paket je skupina razredov, ki tvorijo smiselno celoto (npr. paket razredov za delo z datotekami java.io).
Če definiramo metodo ali komponento in ne povemo kakšen dostop ima, se privzame, da ima dostop protected.

Objekta this in super

V Javi besedica this pomeni objekt, na katerem se izvaja objektna metoda. Vemo že, da je do komponente x v objektu, na katerem se izvaja objektna metoda, dostopamo s this.x. Okrajšano to lahko pišemo tudi x. Podobno pravilo velja za dostop do objektne metode: namesto this.f(x,y,z) lahko pišemo f(x,y,z).
Poleg tega ima this še eno uporabo: na začetku konstruktorja lahko pokličemo kak drug konstruktor s klicem this(...). To bomo ponazorili s primerom, najprej pa naštejmo vsa pravila za uporabo this.
this
objekt, na katerem se izvaja objektna metoda
this.x
(krajši zapis: x)
komponenta x v objektu, na katerem se izvaja objektna metoda.
this.f(...)
(krajši zapis: f(...))
pokliči metodo f na objektu this.
this(x,...,y)
pokliči konstruktor z argumenti x,...,y; ta uporaba je možna le na začetku konstruktorja.
Naslednji primer prikazuje, kako se uporabi this za klic konstruktorja:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Foo {
  int x;
  int y;
  int z;

  public Foo(int x, int y) {
    this.x = x;
    this.y = y;
    this.z = x + y;
  }

  public Foo(int x) {
    this(x, x + 2);
    this.z = 1;
  }
}
Ko izvedemo ukaz
Foo a = new Foo(20);
se izvede 12. vrstica z vrednostjo x = 20. V 13. vrstici se pokliče konstruktor za razred Foo z argumentoma 20 in 22. Izvajanje se prenese v konstruktor v 6. vrstici z vrednostma x = 20, y = 22. V 7., 8. in 9. vrstici se nastavijo komponente this.x = 20, this.y = 22 in this.z = 42. Klic tega konstruktorja se zaključi in izvajanje se vrne v 14. vrstico, kjer se nastavi this.z = 1. Končni rezultat je objekt a razreda Foo, ki ima komponente
a.x == 20
a.y == 22
a.z == 1
Poleg this pozna Java še objekt super. Denimo, da imamo razred Foo in podrazred Qux:
public class Foo {
  int x;

  public void mojaMetoda() {
    System.out.println("Ti si ena krava.\n");
  }
}

public class Qux extends Foo {
  int y;

  public void mojaMetoda() {
    System.out.println("Ti si ena koza.\n");
  }

  public void f() {
    this.mojaMetoda();
    super.mojaMetoda();
  }
}
Ko izvedemo ukaz:
(new Qux()).f();
se na zaslon izpiše:
Ti si ena koza.
Ti si ena krava.
Vidimo, da se pri klicu this.mojaMetoda() pokliče objektna metoda mojaMetoda() iz razreda Qux, pri klicu super.mojaMetoda() pa se pokliče objektna metoda mojaMetoda() iz nadrazreda razreda Qux.
public class Foo {
  int x;

  public void g() { ... }
}

public class Qux extends Foo {
  int x;

  public void g() { ... }
}
V objektni metodi razreda Qux je super objekt, na katerem se je poklicala metoda, vendar se ga obravnava kot pripadnika nadrazredaFoo. Torej pomeni:

Osnove vmesnikov

Poleg razredov (class) Java pozna še en osnovni konstrukt, ki se imenuje vmesniki (interface). V tej lekciji se z vmesniki ne bomo preveč ukvarjali, le toliko, da bomo znali uporabljati vmesnike iz Javine standardne knjižnice.
Vmesnik sestoji iz seznama deklaracij metod. Na primer:
KomunikacijskaNaprava.java
1
2
3
4
5
6
public interface KomunikacijskaNaprava {
    public boolean poklici(String stevilka);
    public void prekini_zvezo();
    public void poslji_sporocilo(String s);
    public String sprejmi_sporocilo();
}
KomunikacijskaNaprava je vmesnik (interface) in ne razred (class). V njem so deklarirane štiri metode za komunikacijo.
Vmesnik uporabimo z določilom "implements", takole:
public class Mobitel implements KomunikacijskaNaprava {
   ...

   public boolean poklici(String stevilka) { ... }

   public void prekini_zvezo() { ... }

   public void poslji_sporocilo(String s) { ... }

   public String sprejmi_sporocilo() { ... }      

   ...
}
S tem smo povedali, da razred Mobitelustreza vmesniku KomunikacijskaNaprava. To pomeni, da vsebuje vse metode, ki so deklarirane v KomunikacijskaNaprava. Vmesnik uporabimo takole:
KomunikacijskaNaprava m = new Mobitel(...);
if (m.poklici("014766500")) {
    m.poslji_sporocilo("Pridem cez 15 minut.");
    m.prekini_zvezo();
} else {
    System.out.println("Zasedeno.\n");
}
public class A implements I {
  ...
}
Razred A ustreza vmesniku I. To pomeni, da A vsebuje vse metode, ki so deklarirane v vmesniku I.
Razred lahko ustreza večim vmesnikom. V tem primeru naštejemo vse vmesnike, ločene z vejicami:
public class SuperMobitel implements KomunikacijskaNaprava, Kalkulator {
   ...
}
Razred torej vedno deduje od kvečjemu enega nadrazreda, ustreza pa lahko večim vmesnikom.
Naloga 6
[rešitev]

Izjeme

Izjema (angl. "exception") je poseben dogodek, ki se pripeti, kadar pride v programu do napake. Najpogostejše izjeme v Javi so:
ArithmeticException
Sproži se pri deljenju z nič:
Delenje.java
1
2
3
4
5
6
public class Delenje {
    public static void main(String[] args) {
	int a = 0;
	int b = 20/a;
    }
}
> java Delenje
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Delenje.main(Delenje.java:4)
ArrayIndexOutOfBoundsException
Sproži se pri naslavljanju neobstoječega elementa tabele:
Tabela.java
1
2
3
4
5
6
public class Tabela {
    public static void main(String[] args) {
	int[] a = {0, 3, 1, 7};
	int b = a[20];
    }
}
> java Tabela
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at Tabela.main(Tabela.java:4)
StringIndexOutOfBoundsException
Sproži se, če program dostopa do neobstoječega indeksa v nizu:
Niz.java
1
2
3
4
5
6
public class Niz {
    public static void main(String[] args) {
	String s = "abcdef";
	char c = s.charAt(31);
    }
}
> java Niz
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 31
	at java.lang.String.charAt(String.java:438)
	at Niz.main(Niz.java:4)
NullPointerException
Sproži se, če program kliče metodo na nedefiniranem objektu null:
Null.java
1
2
3
4
5
6
7
public class Null {
    static String s;

    public static void main(String[] args) {
	char c = s.charAt(3);
    }
}
> java Null
Exception in thread "main" java.lang.NullPointerException
	at Null.main(Null.java:5)
FileNotFoundException
Sproži se, ko program odpre datoteko, ki ne obstaja:
Datoteka.java
1
2
3
4
5
6
7
import java.io.*;

public class Datoteka {
    public static void main(String[] args)  throws IOException {
	FileReader f = new FileReader(args[0]);
    }
}
> java Datoteka blabla.txt
Exception in thread "main" java.io.FileNotFoundException:
blabla.txt (No such file or directory)
	at java.io.FileInputStream.open(Native Method)
	at java.io.FileInputStream.<init>(FileInputStream.java:106)
	at java.io.FileInputStream.<init>(FileInputStream.java:69)
	at java.io.FileReader.<init>(FileReader.java:42)
	at Datoteka.main(Datoteka.java:5)
Ko se sproži izjema, se prevajanje programa prekine. To ni vedno zaželeno. Na primer, če uporabnik navede neobstoječo datoteko, potem je bolje, če se program ne prekine, ampak izpiše sporočilo, da taka datoteka ne obstaja.
Kadar napišemo metodo, ki bi lahko sprožila izjemo, moramo v deklaraciji metode to povedati z določilom throws. Če pozabimo dodati throws, nas prevajalnik opozori na napako.
public int mojaMetoda(...) throws ImeIzjeme {
  ...
}
V Javi lahko izjeme prestrežemo s konstruktom
try {
 A;
}
catch (ImeIzjeme e) {
 B;
}
To pomeni: "Izvedi A. Če se med izvajanjem sproži izjema ImeIzjeme, jo prestrezi in izvedi B."
Na primer, napišimo program, ki z ukazne vrstice dobi ime datoteke in izpiše njeno vsebino na zaslon. Če datoteka ne obstaja, izpiše sporočilo o napaki:
IzpisiDatoteko.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;

public class IzpisiDatoteko {
    public static void main(String[] args) {
	
	String ime = args[0];

	try {
	    BufferedReader datoteka = new BufferedReader(new FileReader(ime));
	    while(datoteka.ready()) {
		System.out.println(datoteka.readLine());
	    }
	    datoteka.close();
	}
	catch (FileNotFoundException e) {
	    System.out.println("Datoteka " + ime + " ne obstaja.");
	}
    }

}
> java IzpisiDatoteko Niz.java
public class Niz {
    public static void main(String[] args) {
	String s = "abcdef";
	char c = s.charAt(31);
    }
}

> java IzpisiDatoteko blablabla.txt
Datoteka blablabla.txt ne obstaja.
Naloga 7
Popravi program IzpisiDatoteko.java tako, da v primeru, ko datoteka ne obstaja, uporabnika vpraša za novo ime. Če uporabnik vnese prazno ime (pritisne Enter), naj se program konča, sicer pa naj poskusi z novim imenom. Če po treh poskusih uporabnik še vedno ni vnesel imena obstoječe datoteke, naj se program konča.
Namig
Uporabi dve pomožni spremenljivki. Prva je boolean uspeh in ima vrednost false. Ko program uspešno izpiše datoteko, naj jo nastavi na true. Druga pomožna spremenljivka šteje, koliko je bilo neuspešnih poskusov. Če to število preseže 3, program konča z delom.
Shema glavnega dela programa:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.*;

public class IzpisiDatoteko2 {
    public static void main(String[] args) throws IOException {
	String ime = args[0];
	boolean uspeh = false;
	int neuspehi = 0;
	
	do {
	    try {
		BufferedReader datoteka =
		    new BufferedReader(new FileReader(ime));
		while(datoteka.ready()) {
		    System.out.println(datoteka.readLine());
		}
		datoteka.close();
		uspeh = true;
	    }
	    catch (FileNotFoundException e) {
		neuspehi = neuspehi + 1;
                // tu vprasamo uporabnika za novo ime
		}
	    }
	} while (//tu napisi ustrezni pogoj);
    }

}
[rešitev]

Rešitve nalog

Naloga 1: Objektni zajci

Diagram, ki ponazarja stanje, po izvedenih ukazih:
Diagram zajčjih objektov
Naredijo se tri kopije komponente masa, vsaka za enega zajca. Njihove vrednosti so 0.12, 0.09 in 0.11. Na vrednost 2.0 jih nastavimo takole:
z1.masa = 2.0;
z2.masa = 2.0;
z3.masa = 2.0;
Naredi se ena kopija statične komponente max_starost z vrednostjo 48. Na vrednost 36 jo nastavimo z ukazom
Zajec.max_starost = 36;

Naloga 2

Klic metode t.g(50) nima dostopa do komponente s.y. Ima dostop do komponent this.y = t.y in do statične komponente Foo.x.

Naloga 3

  1. Nadrazred razreda Applet je razred Panel.
  2. Da, to je razred javax.swing.JApplet.
  3. Applet podeduje metode od svojega nadrazreda in vseh njegovih prednikov, se pravi: Panel, Container, Component, Object.
  4. Metodo getWidth podeduje Applet od razreda Component.
  5. Metoda resize je definirana v razredu Applet, zato je le-ta ne podeduje.
  6. Od razreda Panel razred Applet podeduje metodo addNotify (in seveda še vse metode, ki jih Panel podeduje od svojih prednikov).

Naloga 5

Izvede se metoda bla() iz razreda Foo, se pravi, da se r nastavi na vrednost 5.

Naloga 6

  1. Applet ustreza vmesnikom Accessible, ImageObserver, MenuContainer, in Serializable
  2. Vmesnik ImageObserver predpisuje metodo public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height).
  3. Iz dokumentacije: "An asynchronous update interface for receiving notifications about Image information as the Image is constructed." Razred, ki ustreza vmesniku ImageObserver ima posebno metodo imageUpdate, preko katere sperejma obvestila o tem kako se dana slika (Image) riše. To se na primer uporablja v brskalnikih kot sta Explorer in Netscape, ki prikazujeta na pol narisane slike medtem, ko se le-te nalagajo iz Interneta.

Naloga 7

IzpisiDatoteko2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.io.*;

public class IzpisiDatoteko2 {
    public static void main(String[] args) throws IOException {
	
	BufferedReader vhod =
	    new BufferedReader(new InputStreamReader(System.in));
	String ime = args[0];
	boolean uspeh = false;
	int neuspehi = 0;
	
	do {
	    try {
		BufferedReader datoteka =
		    new BufferedReader(new FileReader(ime));
		while(datoteka.ready()) {
		    System.out.println(datoteka.readLine());
		}
		datoteka.close();
		uspeh = true;
	    }
	    catch (FileNotFoundException e) {
		neuspehi = neuspehi + 1;
		if (neuspehi < 3) {
		    System.out.println("Datoteka " + ime + " ne obstaja.");
		    System.out.print("Prosim vpisi novo ime (prtisni Enter za konec): ");
		    ime = vhod.readLine();
		    if (ime.equals("")) {
			uspeh = true;
		    }
		    else {
			uspeh = false;
		    }
		}
	    }
	} while (!uspeh && neuspehi < 3);
    }

}