Praktikum 3
Objektid. Klassid.
Teemad
Objektid ja klassid. Konstruktorid. Isendiloome. Muutujate ja meetodite nähtavus.
Pärast selle praktikumi läbimist oskab üliõpilane
- luua klassitüüpi objekte ehk isendeid;
- luua ning kasutada erinevaid konstruktoreid ja isendivälju;
- kasutada piiritlejaid;
- kasutada võtmesõna
this
; - luua ja kasutada erinevat tüüpi massiive;
- selgitada algtüübi ja viittüübi erinevusi.
Veidi massiividest
Enne, kui lähme praktikumi põhiosa juurde, meenutame pisut massiividega seonduvat (pikemalt oli eelmise praktikumi materjalis).
Paljude ülesannete puhul on mõistlik mingit hulka ühte tüüpi muutujad koos käsitleda. Näiteks kuue ujukomaarvu puhul võime kasutada massiivi, mille tekitame massiiviloomega:
double[] arvud = new double[6];
Nüüd on olemas muutujad arvud[0]
, arvud[1]
, arvud[2]
, arvud[3]
, arvud[4]
ja arvud[5]
. Vaikimisi on neil väärtuseks 0.0
. Uusi väärtusi saab omistada nagu ikka muutujatele väärtusi omistame, nt. arvud[3] = 4.6;
.
Massiivi elemendiga saame teha tehteid (nt. 34*arvud[3]
), võime neid ekraanile väljastada: System.out.println(arvud[3]);
Kui aga tahaksime kogu massiivi väljastada, siis rea System.out.println(arvud);
toimel tuleb ekraanile midagi sellist: [D@15b7986
. Muutuja arvud
väärtuseks ei ole massiiv ise vaid viit (reference) massiivile. (Natuke pikemalt käsitleme seda temaatikat praktikumi lõpuosas.)
Kui tahame kõik massiivi elemendid ekraanile saada, siis on sobiv vahend for
-tsükkel. Näiteks programmilõik
for (int i = 0; i < arvud.length; i++) { System.out.println(arvud[i]); }
või ka
for (double elem : arvud) { System.out.println(elem); }
Massiivi suurus on fikseeritud, nii et elemente lisada, nii nagu Pythonis, pole võimalik. Kui on soovi pikkust programmi töö käigus vabalt muuta, elemente erinevatesse kohtadesse lisada ja neid eemaldada, siis selleks on Javas teised vahendid, mida õpime juba järgmises praktikumis.
Enne, kui läheme tänase praktikumi põhiosa juurde, meenutame veel eelmises praktikumis käsitletud käsurea argumente. Tegemist on sõnemassiiviga, mille elemendid saavad väärtused programmi käivitamisel ja mille nimi määratakse peameetodi formaalse parameetri nimena. Kuigi ka IDEst käivitamisel saab argumentide väärtusi määrata, on see ilmekam käsurealt käivitades pärast kompileerimist (nagu 1. praktikumis käsitletud):
java Klassinimi Tartu Riia
Aga nüüd klasside ja isendite juurde
Javas programmeerimine seisneb klasside koostamises. Klasse koostasime juba ka eelmistes praktikumides. Kuna need sisaldasid peameetodit (main
), siis võib neid nimetada peaklassiks ja neid sai käivitada. Samuti kasutasime klassi Math
-meetodeid. Nüüd asume koostama klasse, mis on kui uued andmetüübid, mida saab kasutada üsna analoogiliselt lihttüüpidega (int
, char
, ... ). Väga olulisel kohal on koostatud klasside isendite (objektide) loomine. Klassikirjelduses on oma koht andmetel (mis näitavad olekut) ja meetoditel (mis kirjeldavad käitumist). Andmeid kujutatakse muutujate abil. Kuna muutujad saavad väärtused konkreetsete isendite loomisel, siis nimetatakse neid isendiväljadeks (ka isendimuutujateks, inglise keeles fields).
Olgu meil klass Isik
, milles on kaks välja:
class Isik { String nimi; // isendiväli isiku nime jaoks double pikkus; // isendiväli isiku pikkuse jaoks }
Olemegi loonud uue andmetüübi, mis sisaldab kohta sõnele (nime jaoks) ja ujukomaarvule (pikkuse jaoks).
Isendi loomine võiks toimuda peaklassi (nt. TestIsik
) peameetodis (main
). (Nimi TestIsik ei tähenda siin, et tegemist oleks mingit eriliiki isikuga vaid klassiga, mis on mõeldud klassi Isik
isendite testimiseks.) Klassi isendeid luuakse käsuga new
:
class TestIsik { public static void main(String[] args) { Isik a = new Isik(); } }
Nüüd on loodud klassi Isik
isend (objekt) a
. Kuigi isend on loodud, on muutujad nimi
ja pikkus
väärtustamata (tegelikult on neil vaikeväärtused, vastavalt null
ja 0.0
). Lisades peaklassi rea System.out.println(a.nimi);
saaksime isendivälja väärtuse ekraanile.
Iga klass peab olema eraldi oma .java
failis ja faili nimi ja klassi nimi võiksid olla samad. S.t. et praegu teil peaks olema tehtud fail Isik.java, kus asub klass Isik
, ja fail TestIsik.java, kus asub klass TestIsik
.
Väärtustamiseks on mitu võimalust. Võib näiteks muuta klassi Isik
kirjeldust
class Isik { String nimi = "Toomas Indrek Elvis"; // isendiväli isiku nime jaoks double pikkus = 1.92; // isendiväli isiku pikkuse jaoks }
Sellisel juhul on aga see mure, et kõik loodud selle klassi isenditel on vastavatel väljadel täpselt samad väärtused. Teine võimalus oleks muuta väärtusi peaklassis. Näiteks
class TestIsik { public static void main(String[] args) { Isik a = new Isik(); a.pikkus = 2.03; System.out.println(a.pikkus); } }
Konstruktor
Eeltoodud väärtustamine pole paraku objektorienteeritud programmeerimise ideoloogiaga kooskõlas. Kui vähegi võimalik, peaks objekti väljad väärtustama hoopis isendi loomise käigus - niimoodi ei ole objekt kordagi vigases seisus, kus tal on osad andmed puudu. Selleks täiendame klassi konstruktoriga (erilise protseduuriga, mis rakendub isendiloome käigus).
class Isik { String nimi; // isendiväli isiku nime jaoks double pikkus; // isendiväli isiku pikkuse jaoks // konstruktor Isik(String isikuNimi, double isikuPikkus) { nimi = isikuNimi; pikkus = isikuPikkus; } }
Nüüd saab isendeid luua järgmiselt:
Isik a = new Isik("Juhan Juurikas", 1.99); Isik b = new Isik("Madli Mallikas", 1.55);
Muutujaid a
ja b
käsitletakse siin kui tavalisi muutujaid, kuid nende tüübiks on Isik
. Neid nimetatakse viittüüpi muutujateks, sest nende väärtuseks on viit klassi isendile. (Täpsemalt räägime sellest praktikumi lõpuosas.)
Ülesanne 1
Olgu meil klassi Isik
kasutamiseks järgmine peaklass
class TestIsik { public static void main (String[] argv) { Isik a = new Isik("Juhan Juurikas", 1.99); System.out.println("Isik a on " + a); } }
Sisestage see programm ja käivitage. Milline on tulemus?
Tulemus ei ole hästi loetav, sest objekt a
ei kuulu Java standardobjektide hulka.
Meetod toString
Selleks, et Java suudaks programmeerija kirjeldatud objekte arusaadaval viisil ekraanile tuua, võib (kuid saab ka teisiti) klassi Isik
kirjeldusse lisada meetodi toString()
, mis määrab, kuidas antud objekt tekstina välja näeb. Näiteks klassi Isik
puhul võib see meetod olla järgmine:
public String toString() { return "(" + nimi + "; " + pikkus + ")"; }
Ülesanne 2
Täiendage klassi Isik
meetodiga toString()
. Testklassis looge mõni isik ja väljastage ekraanile nende andmed, näiteks järgmise rea abil:
System.out.println(a.toString());
Tegelikult on toString
mõneti ebatavaline meetod, mis rakendub automaatselt isendi sõneksteisendusel (nt. väljastamisel). Seega võime kasutada ka
System.out.println(a);
Meetod toString
on tegelikult kasutatav ka selliste klasside isendite puhul, kus seda meetodit eraldi kirja pandud polegi. Sellisel juhul toimib meetod toString
, mis on kirjeldatud ülemklassis. (Ülemklassid ja alamklassid on päriluse terminid. Pärilus on aga objektorienteeritud programmeerimise põhialuseid, millest lähemalt räägime juba varsti.) Kui ülemklassi ilmutatult märgitud pole, siis on selleks klass Object
. Klassi Object
defineeritud isendimeetod toString()
annabki selle mõneti ehk kummalisena tunduva @-märgiga kuju.
Piiritlejad private, protected ja public
Nagu ülalpool mainisime saab isendivälja väärtusi muuta testklassist
a.pikkus = 1.95; // isendi a väljale pikkus omistatakse 1.95
Isendiväljade otsekasutuse (nt. a.pikkus = 1.95
) saab keelata, kui nende kirjeldamisel kirjutada muutuja nime ette piiritleja private
. Näiteks
private String nimi; private double pikkus;
Muutujate ja meetodite nähtavust ning kasutust saabki reguleerida piiritlejatega public
, private
ning protected
. Neist public
määrab piiranguteta, private
klassisisese ning protected
klassi- ja selle alamklasside-sisese kasutusõiguse. Kui juurdepääsu määravat piiritlejat pole, siis vaikimisi on juurdepääs olemas sama paketi piires.
Get- ja set-meetodid
Tavaliselt väärtustatakse isendiväljad klassi konstruktorite ja meetodite abil. Privaatse isendivälja väärtuse tuvastamiseks on mõeldud nn. piilumeetod, mille peamiseks ülesandeks on tagastada vastava muutuja väärtus. Näiteks
public String getNimi() { return nimi; } public double getPikkus() { return pikkus; }
Analoogiliselt saab luua ka meetodid väärtuste muutmiseks
public void setNimi(String nimi) { this.nimi = nimi; } public void setPikkus(double pikkus) { this.pikkus = pikkus; }
Kuna neid meetodeid on sageli vaja, IDE oskab neid automaatselt lisada. Eclipse puhul vali Source-menüüst Generate Getters and Setters
, IntelliJ puhul Code-menüüst Generate
.
Võimalusel tuleb siiski väljade väärtused juba konstruktoris seada. Väljade väärtuse hilisem muutmine set-meetoditega muudab koodi mõistmise keerulisemaks, sest klassile peale vaadates ei ole ilmne, mis hetkel väljad mingi konkreetse väärtuse on saanud (kui üldse).
Võtmesõna this
kasutatakse isendiväljadele viitamisel, kui konstruktori või meetodi formaalsete parameetrite nimed langevad kokku isendiväljade nimedega. Võtmesõna this
käitub nagu automaatselt tekitatud isendiväli, mis viitab alati objektile endale. See on kättesaadav kõigis objekti isendimeetodites (static meetodid pole objektiga seotud, seal see ei toimi).
Meetodeid saab kasutada näiteks testklassis koos muutujanimega nt. a.setNimi("Evelin");
.
Objektorienteeritud lähenemise üks olulisi mehhanisme on kapseldamine (encapsulation): objekti realisatsiooni detailid varjatakse ära. Objekti kasutaja ei tea, kuidas andmestruktuurid ja operatsioonid on realiseeritud, ainult objekt ise teab. Objekti andmestruktuuridele saab juurde ainult antud objekti operatsioonide kaudu. See võimaldab objekti sisemuse asendada uuega, ilma, et muus osas mingeid muutusi oleks vaja teha. Nt. getNimi()
tegelikult võib tagastada väärtuse, mis ühendab mitu isendivälja (return eesnimi + " " + perenimi
) väärtust. Samuti meetodis väärtuse muutmiseks võib esialgu kontrollida, kas uued andmed üldse sobivad (nt. setPikkus
ei pea olema nõus negatiivse parameetriga). Kõikidel isendiväljadel ei pea olema get
- ja/või set
-meetodeid. Mõned isendiväljad võivad olla ainult klassisisesed ja väljapoole ei pea neid näha olema (s.t. ei pea olema get
- ja set
-meetodeid). Samuti võib olla isendivälju, mida ei saagi muuta, näiteks seatakse väärtus konstruktoris ning hiljem polegi seda võimalik muuta (set
-meetodit ei olegi, get
-meetod võib olla).
Veel konstruktoritest
Eespool koostasime konstruktori, mis isendiloomel rakendamisel vajas kahte argumenti. Sama saab kirjutada ka võtmesõna this
abil.
public Isik(String nimi, double pikkus) { // isendiväljad nimi ja pikkus saavad väärtusteks // konstruktori parameetrite väärtused this.nimi = nimi; this.pikkus = pikkus; }
Ka konstrukorite kirjutamine IDEs mugavaks tehtud. Eclipse-is vali Source-menüüst Generate Constructor Using Fields
, IntelliJ puhul Code-menüüst Generate
. (On ka genereerimine ülemklassi abil, aga seda me käsitleme pärilusega koos.)
Konstruktorit võib käsitleda kui erilist meetodit kolme tunnusega:
- konstruktori nimi langeb kokku klassi nimega;
- konstruktori nime ette ei kirjutata tagastustüüpi;
- konstruktori poole pöördumine toimub käsuga
new
antud klassi isendi loomisel ja konstruktor tagastab viida loodud isendile.
Kui klassis pole kirjeldatud ühtegi konstruktorit, siis Java lisab sinna ilma argumentideta vaikekonstruktori. Praktikumi algupoolel just seda kasutasimegi: Isik a = new Isik();
.
Samamoodi (Isik a = new Isik()
) kasutatakse ka parameetriteta konstruktorit
public Isik() { nimi = "Nimetu"; pikkus = 0.0; }
Konstruktoreid võib klassis olla mitu, sel juhul on tegemist konstruktorite üledefineerimisega. Ühe ja sama klassi konstruktorid peavad üksteisest erinema signatuuri (formaalsete parameetrite arv ja nende tüübid) poolest. Samuti võib klassis olla sama nimega meetodeid, sellisel juhul peavad need erinema formaalsete parameetrite arvu ja/või nende tüüpide poolest.
Kahe konstruktoriga klass Isik
kirjelduse algusosa on järgmine:
public class Isik { private String nimi; private double pikkus; public Isik(String isikuNimi, double isikuPikkus) { nimi = isikuNimi; pikkus = isikuPikkus; } public Isik() { nimi = "Nimetu"; pikkus = 0.0; } // ERINEVAD MEETODID }
See, milline konstruktor täidetakse, määratakse argumentide arvu ja tüüpide järgi:
Isik d = new Isik(); Isik e = new Isik("Ülli Õpilane", 2.05);
Võtmesõna this
abil on võimalik ühe konstruktori sees pöörduda teise sama klassi konstruktori poole. Klassi Isik
viimase toodud versiooniga samaväärne klass:
public class Isik { private String nimi; private double pikkus; public Isik(String isikuNimi, double isikuPikkus) { nimi = isikuNimi; pikkus = isikuPikkus; } public Isik() { this("Nimetu", 0.0); } //ERINEVAD MEETODID }
Meetodid
Eelnev osa oli põhiliselt andmetest - kuidas saab isendiväljadele väärtusi anda, neid vaadata jms. Edasi vaatleme, kuidas saab objekti "õpetada käituma". Tegelikult juba eelmises lõigus olid käsitlemisel get-
ja set-
meetodid, samuti on meetod ka toString
. Meetodite üldine ideoloogia on sama, mis oli eelmistes praktikumides, kus küll veel polnud isendimeetodeid.
Muutujat või meetodit, mis otseselt ei seostu antud klassi isendiga, nimetatakse vastavalt klassimuutujaks või -meetodiks. (Meenutame nt. klassi Math
.) Eraldamaks neid meetodeid ja muutujaid otseselt isenditega seotutest, lisatakse nende kirjelduste ette piiritleja static
, samuti ei ole nende kasutamiseks vajalik klassi isendite olemasolu.
Isendimeetodid see-eest on seotud konkreetse objektiga. Selle tulemusena on isendimeetoditel ligipääs kõigile seotud objekti isendiväljadele, mida nad ka tihtipeale kasutavad. Näiteks sõne küljes olevaid meetodeid ei saa kasutada ilma konkreetset sõne täpsustamata.
Mäletatavasti peavad meetodil olema tagastustüüp, nimi ning parameetrite tüübid ja nimed (kui parameetreid üldse on). Püüame koostada meetodi, mis leiab isiku pikkuse järgi klassikalise tehnika suusakepi pikkuse sentimeetrites. Esimese hooga võiks arvata, et pikkus tuleks argumendina ette anda. Saaks tõesti ka nii, aga kuna pikkus on isendiväljal olemas, siis on mõistlik seda ära kasutada.
public int suusakepiPikkus() { return (int) Math.round(0.85 * pikkus * 100); }
Isendimeetodit saab väljaspool seda klassi kasutada vaid isendiga seotult, nt.
Isik e = new Isik("Ülli Õpilane", 2.05); // loob isendi System.out.println(e.suusakepiPikkus()); // kasutab isendi meetodit
Klassi isendimeetodite sees saab kutsuda sama klassi isendimeetodeid ilma isendit eraldi märkimata. Võib kirjutada lihtsalt meetodi väljakutse ja see käivitatakse automaatselt sama isendi (this) peal.
Ülesanne 3 (kontroll)
Täiendage nüüd klassi Isik
nii, et seal oleks vähemasti neli isendivälja (nimi, pikkus, isikukood ja näiteks mass). Klassis peab olema konstruktor, mis väljad väärtustab. Isendiväljadele peavad olema vastavad get
- ja set
-meetodid (isikukood seatakse konstruktoris ja hiljem seda muuta ei saa, pikkuse ja massi muutmisel tuleb kontrollida, kas uued andmed üldse sobivad). Samuti klassis on meetod toString
ning lisaks veel mõned meetodid (nt. kehamassiindeksi või suusa pikkuse arvutamiseks). Vähemasti üks meetod peaks vajama ka argumente. (Argumentideks peaksid olema lisaandmed, mitte isendiväljad.) Katsetage loodud meetodeid testklassis.
Massiivid
Eelpool oli juttu nt. arvude massiividest. Massiivis on üht tüüpi elemendid. See tüüp võib olla aga ka viittüüp.
Näitena koostame klassi Raamat
:
public class Raamat { private String autor; private String pealkiri; public Raamat(String autor, String pealkiri) { this.autor = autor; this.pealkiri = pealkiri; } }
Koostage ka vastav testklass, milles võime luua selle klassi isendeid, nt.
Raamat kevade = new Raamat("Oskar Luts", "Kevade");
Klassi Raamat
isenditest massiivi loomine toimub järgnevalt:
Raamat[] riiul = new Raamat[100];
Muutuja riiul
sisaldab viitasid raamatutele, aga hetkel pole seal veel ühtegi (sisulist) viita. Võite proovida nt. väljastada
System.out.println(riiul[8]);
Paneme Kevade "riiulisse":
riiul[8]=kevade;
Proovige nüüd väljastada.
Lisage nüüd klassi Raamat
veel toString
meetod.
Proovime tekitada raamatuid "hulgi":
String autor = "Eduard Vilde"; for (int i = 0; i < riiul.length; i++) { riiul[i] = new Raamat(autor, "Kogutud teosed " + String.valueOf(i + 1)); } System.out.println("10. raamat riiulil on " + riiul[9] + ".");
Ülesanne 4 (kontroll)
Muutke klassi Raamat
nii, et autor oleks hoopis Isik
-tüüpi.
private String autor; --> private Isik autor;
Viittüüp vs algtüüp
Praktikumi viimases lõigus räägime mõnede näidete põhjal viittüübi (reference type) ja algtüübi (primitive type) erinevustest. Piirdume küllalt lihtsustatud käsitlusega, millest aga võiks piisata käesoleva kursuse jaoks.
Iga muutuja jaoks eraldatakse mälus koht, kus vastavat väärtust hoida. Kui me deklareerime muutuja, siis ütleme sellega, mis tüüpi väärtusega tegemist on. Kui muutuja on algtüüpi (byte
, short
, int
, long
, float
, double
, char
, boolean
), siis see väärtus on algtüüpi. Viittüüpi muutuja (kõik objektid, nt String, Scanner, kõik massiivid ja meie loodud klasside isendid) korral on aga väärtuseks viit vastavale objektile. Kogu aeg me sellele erinevusele mõtlema ei pea, küll aga teatud juhtudel on see väga oluline. Näiteks kui algtüüpi muutuja korral omistame muutujale väärtuseks teise muutuja väärtuse, siis tehakse väärtusest koopia ja kummaskis muutujas on koopia samast väärtusest. Viittüüpi muutuja korral on aga väärtuseks viit ja seetõttu tekib natuke teistsugune seos - koopia tehakse viidast, mitte objektist endast! Selle tulemusena saavad mitu muutujat viidata samale objektile. Niisiis programmilõigu
int arv1 = 1632; int arv2 = arv1; arv2 = 1802;
puhul saab arv2
esialgu väärtuseks muutuja arv1
väärtuse 1632 ja seejärel 1802. Muutuja arv1
enda väärtus ei muutu. Kui nüüd väljastame muutujate väärtused, siis saame
System.out.println("arv1 on: " + arv1); System.out.println("arv2 on: " + arv2);
Enne, kui proovite, püüdke tulemusi ennustada.
Viittüübi tutvustamiseks loome kõigepealt ühe väga lakoonilise klassi, kus on vaid üks int
-tüüpi isendiväli.
public class Arv { public int arv; }
Teeme nüüd samalaadsete väärtustamistega programmilõigu.
Arv viitarv1 = new Arv(); viitarv1.arv = 1632; Arv viitarv2 = new Arv(); viitarv2 = viitarv1; viitarv2.arv = 1802; System.out.println("viitarv1.arv on: " + viitarv1.arv); System.out.println("viitarv2.arv on: " + viitarv2.arv);
Enne, kui proovite, püüdke ka neid tulemusi ennustada.
(Näide on inspireeritud raamatust
, kus on palju huvitavat informatsiooni.)
Ka massiivid on käsitletavad viittüüpi objektidena. Näiteks
int[] arvud1 = {1632}; int[] arvud2 = arvud1; arvud2[0] = 1802; System.out.println("arvud1[0] on: " + arvud1[0]); System.out.println("arvud2[0] on: " + arvud2[0]);
Enne, kui proovite, püüdke ka neid tulemusi ennustada.
Kui on vaja massiive kopeerida, siis saaks seda teha
- elementhaaval kopeerides;
- kasutades klassi
System
meetoditarraycopy
; - kasutades meetodit
clone
.
Ülesanne 5
Katsetage eeltoodud näiteid ja kontrollige oma ennustuste paikapidavust.
Ülesanne 6 (kontroll)
Klassis Elektrijaam
on double
tüüpi isendiväli elektrihind, mis väärtustatakse konstruktoris. Hinnal on ka vastavad get
- ja set
-meetodid.
Klassis Elektriauto
on privaatsed isendiväljad automargi (String
) jaoks, elektrikulu (double
) 100 km-ile jaoks (kWh/100km), laadimisaja minutites (int
) jaoks, sõiduulatuse (mis näitab, mitu kilomeetrit on võimalik sõita ühe laadimisega) (int
) jaoks ja elektrijaama (Elektrijaam
) jaoks. Klassis on konstruktor, mis väärtustab kõik väljad. On ka vähemalt järgmised meetodid:
- Laadimisaja ja elektrijaama jaoks on vastavad
get
- jaset
-meetodid.set
-meetodis on laadimisaja jaoks andmete sobivuse kontroll. - Ilma argumentideta isendimeetod (
double
-tüüpi)maksumus100
, mis näitab sajakilomeetrilise reisi maksumust (elektrikulu korda elektri hind). - Isendimeetod (
double
-tüüpi) maksumus, mis saab argumendina täisarvu (teepikkus kilomeetrites) ja näitab reisi maksumust antud autoga (teepikkus korda sajakilomeetrilise reisi maksumus ja jagatud sajaga). (Kasutada vastavat meetodit). double
-tüüpi isendimeetodreisiKestus
, millel on 2 argumenti: teepikkus kilomeetrites (int
-tüüpi) ja keskmine kiirus km/h (double
-tüüpi). MeetodreisiKestus
tagastab reisiks kulutatud aja ((teepikkus/sõiduulatus)*laadimisaeg tundides + teepikkus/kiirus).- On ka meetod
toString
, mis võimaldab auto infot mõistikult ekraanil kujutada, tuues välja ka 100-kilomeetrilise reisi maksumuse. (Kasutada vastavat meetodit).
Lisaks koostage testklass (peaklass). Testklassis luuakse elektrijaama isend, kus elektrihinnaks määratakse 0,15 (eur/kWh) ja erinevad autod. Testklassis testitakse ka erinevate isendimeetodite tööd. Testimisel väljastada alati ka kommentaar tekstina, et mida parasjagu väljastatakse. Väljund peab olema viisakas ja loetav.
Andmed testimiseks leiate nt. lehelt http://www.elektriauto.ee/
.
Lisaülesanne (neile, kes kasutavad arvutiklasside arvuteid)
Failide transportimine FileZilla abil
FileZilla on tasuta programm, mille saab alla laadida oma arvutisse veebilehelt https://filezilla-project.org/download.php?type=client
Oma ülikooli serveri kodukataloogiga andmete vahetamiseks tuleb programm käivitada, avanevas aknas tuleb sisestada kasutajanime ja serveri andmed: https://wiki.ut.ee/display/AA/Failide+transportimine+FileZilla+abil
Kui esmakordselt serverit kasutate, küsitakse teie käest, kas usaldate selle serveri andmeid, vajutage "Jah"("Yes" või "Trust") nuppu. Kui parool ja kasutajanimi on õiged, avaneb aken, kus vasakul on teie arvuti failide kaust ning paremal teie serveri kodukataloog. Failide kopeerimiseks tuleks kopeeritavad failid ära märkida ning hiirega lohistada sobivasse kohta. Nüüd proovige salvestada arvutiklassis tehtud programmid (ehk oma kodukataloogist) oma koduarvutisse ja vastupidi.