Eli olen harjoitellut javan ohjelmointia ja nyt tein tälläisen Televisio-harjoituksen ihan vaan luokkien ja periytymisen harjoittelemisen vuoksi, ei siis mitään käytännön hyötyä ole.
Minulla on luokka Televisio, jolla on aliluokka Samsung ja vielä erillinen pääohjelma näiden testaamiseen.
Miten saisin ohjelmoitua television sulkeutumisen, että kun pääohjelma kutsuu sulje-metodia niin mitään luokan/aliluokan metodia ei voi enää käyttää(eli ei voi vaihtaa kanavia eikä äänenvoimakkuutta) ellei kutsu käynnistys-metodia?
Jos yrittää käyttää niin tulee ilmoitus että Käynnistä ensin televisio, tjtn.
Voit lisätä luokkaan muuttujaan, jossa kerrotaan, onko televisio päällä vai ei. Useimmat metodit toimivat vain, jos televisio on päällä.
Tarkotatko tuota vai ihan pääohjelman luokkaa? Miten sen muuttujan sitten saa silleen että jos pois päältä niin koko televisio ja aliluokka poistuu käytöstä?
kokeilin lisätä allaolevaan koodinpätkään jonkun boolean muuttujan mutta en osannut sitä käyttää mitenkään.
Nyt tuli mieleen että jos lisäisi tuohon koodiin jonkun boolean-muuttujan ja jokaiseen metodiin if(boolean-muuttuja==true) niin ne toimii ja muuten ei. Löytyykö helpompaa keinoa, jossa selviäisi vähemmillä lauseilla. Tässä siis pitäisi kai laittaa jokaiseen metodiin kyseinen lause?
public class Televisio {
int kanava;
int vol;
.
.
.
Luo Televisio-luokkaan boolean-tyyppinen muuttuja käynnissä
, ja luo luokalle metodit käynnistä
, sammuta
ja onkoKäynnissä
, jotka muuttavat muuttujan arvoa todesta epätodeksi ja toisinpäin.
On hyvä luoda muuttujien käsittelyyn omat metodit, varsinkin kun niitä käytetään toisesta luokasta.
package televisiotesti; public class Televisio { private boolean käynnissä = false; private int kanava; private int äänenvoimakkuus = 100; public Televisio() { käynnistä(); } public void käynnistä() { käynnissä = true; } public void sammuta() { käynnissä = false; } public boolean onkoKäynnissä() { return käynnissä; } ... }
Muokkaus. Nähtävästi muokkaustoiminto lähetti uuden viestin...
erkki4 kirjoitti:
Nyt tuli mieleen että jos lisäisi tuohon koodiin jonkun boolean-muuttujan ja jokaiseen metodiin if(boolean-muuttuja==true) niin ne toimii ja muuten ei. Löytyykö helpompaa keinoa, jossa selviäisi vähemmillä lauseilla.
Juuri noin se täytyy tehdä, eikä erityisesti helpompaa keinoa ole.
Macro kirjoitti:
Muokkaus. Nähtävästi muokkaustoiminto lähetti uuden viestin...
Tuskinpa, kun se kaikilla muilla toimii ihan oikein (ja sinullakin, kun vähän yrität). Ellet pysty muuta todistamaan, epäilen, että vika sijaitsee siellä tuolin ja tietokoneen välissä. :)
Opettele käyttämään perintää.
Määrittele tellu-luokka
Määrittele tellu-luokalle metodit siten, että ne tekevät sen halutun default-toiminnan (eli ei tee mittään, palauttaa "tellu ei käynnissä", ym.)
Määrittele samsung tellu-luokasta periytyvänä
Määrittele samsung-luokkaan tellu-luokan metodit override-tyyppisenä.
Määrittele samsung-luokan metodit siten, että ne tekevät samsungille halutut toiminnat (eli kanava vaihdettu, "samsung käynnissä", ym.)
nyt voit testata
Tellu t=new Tellu; t=t.kaynnista("samsung"); // eli t=new samsung; t.onkokaynnissa(); t=t.sammuta(); // eli t=new Tellu; t.onkokaynnissa();
(Ja kun ymmärrät tämän toiminnan niin mietippä interface-määrittelyn ja static-määreen käyttöä)
Mä oon laittanu jo että public class Samsung extends Televisio, eli aliluokkana Samsung. Mitä meinaa nuo override-tyyppiset metodit?
Samsung-luokan täytyy toteuttaa kaikki samat metodit kuin Televisio-luokkakin.
tepokas kirjoitti:
t=t.kaynnista("samsung"); // eli t=new samsung;
No tässä ei ainakaan ole mitään järkeä.
Macro kirjoitti:
Samsung-luokan täytyy toteuttaa kaikki samat metodit kuin Televisio-luokkakin.
Siis Samsung luokan täytyy toteuttaa vain sellaiset metodit, jotka ovat Televisio-luokassa määritetty abstrakteiksi... mitään muuta ei ole pakko...
En oikein tajua tota abstraktin luokan ja metodin merkitystä ja tarvetta.
Esim. http://www.cs.hut.fi/Opinnot/T-106.1206/K2007/pruju/node56.html
Tuossa linkissä on esimerkkikoodissa merkitty Kuvio-luokka abstraktiksi ja sillä on abstrakti metodi laskePintaAla. Niin sehän on myös joka aliluokassa metodina niin miksi sen pitäis olla tuossa Kuvio-luokassa, jos siinä ei tehdä mitään.
Jos joku vois valaista ton abstraktin luokan ja metodin käyttötapaa ja hyötyä. :)
Sen pitää olla Kuvio-luokassa, jotta voidaan sijoittaa vaikka Kolmio-tyyppinen olio Kuvio-tyyppiseen muuttujaan ja silti käyttää kyseistä toimintoa. Muuten Java ei enää tietäisi, että kyseisellä Kuvio-oliolla on pinta-alakin.
Tyhmä kysymys varmaan, mutta minkälaiset metodit kannattaa laittaa abstrakteiksi(vaikka tässä Televisio-samsung luokkamäärittelyissä)?
Kun mitä oon esimerkkejä kattonu niin osa on abstrakteja niissä ja osa taas ei.
Ja kun tehdään luokkia ja niille aliluokkia niin onko se yliluokka yleensä aina abstrakti luokka?
Abstraktiksi kuuluvat ne, joita ei voi järkevästi toteuttaa. Esimerkiksi Kuvio-luokka ei voi järkevästi laskea omaa pinta-alaansa, joten metodin pitää olla abstrakti. Jos metodille on jo yliluokassa mielekäs toteutustapa, sen voi toteuttaa saman tien.
Yliluokka ei läheskään aina ole abstrakti. Esimerkiksi graafisen käyttöliittymän tekstikenttä on täysin toimiva luokka, vaikka se voikin toimia yliluokkana vaikkapa yksisanaiselle tekstikentälle, joka ei hyväksy välilyöntejä.
Kannattaa tutustua Javan apiin (Application Programming Interface), niin näet miten eri luokkien periytymissuhteet voivat toimia ihan "oikeissa" luokkatoteutuksissa.
Metabolix kirjoitti:
tepokas kirjoitti:
t=t.kaynnista("samsung"); // eli t=new samsung;No tässä ei ainakaan ole mitään järkeä.
Ja mikähän siinä nyt oikean mättää? Nimeäminenkö?
Muutetaan rivi seuraavaksi:
t=t.kaynnista("samsung"); // eli t=new samsungKaynnissa;
Eli metodi Tellu::kaynnista(string) palauttaa samsunKaynnissa olion.
Helepottaako?
Nyt samsungKaynnissa-luokka kuvaa tilaa jossa "Tellu on samsung" ja "Tellu on käynnissä" eli tellun-tilaa. Tällöin samsungKaynnissa-luokan metodit oletus-arvoisesti toteuttavat tilan onKaynnissa eikä metodeihin tarvita erillistä tarkastusta onkoKäynnissä.
Ja tätä kait aloittaja kysyi: "Miten koodata Olion tilan vaikutus metodien toimintaan".
tepokas kirjoitti:
Metabolix kirjoitti:
tepokas kirjoitti:
t=t.kaynnista("samsung"); // eli t=new samsung;No tässä ei ainakaan ole mitään järkeä.
Ja mikähän siinä nyt oikean mättää? Nimeäminenkö?
Koko ajatus mättää, koska koodi ei muuta television tilaa vaan luo kokonaan uuden television. Nyt siis televisiota ei voi lainkaan käynnistää, vaan on olemassa kahdenlaisia televisioita: aina sammutettuja ja aina käynnistettyjä. Jos vaikka Pekka ja Maija istuvat katsomaan sinun televisiotasi, virtanappulasta putkahtaakin molemmille oma töllö – ja kaiken kukkuraksi se alkuperäinen pysyy sammutettuna. Erityisen hienoa ominaisuudessa on, että yhden telkkarin virtanapista saa revittyä minkä tahansa merkkisiä laitteita.
Tässä on vielä käytännön demonstraatio ideasi suurimmasta viasta:
public class Main { class Pekka { public void avaaTelkkari(Televisio t) { t=t.kaynnista("samsung"); // Poks, tuli uusi telkkari! t.etsiOhjelma("urheilu"); } } class Maija { public void avaaTelkkari(Televisio t) { t=t.kaynnista("samsung"); // Poks, tuli uusi telkkari! t.etsiOhjelma("nyyhkyleffa"); } } public static void main(String[] args) { Televisio t = new Televisio(); Maija m = new Maija(); Pekka p = new Pekka(); p.avaaTelkkari(t); m.avaaTelkkari(t); if (!t.onkoKaynnissa()) { System.err.println("Hupsista keikkaa! Kaksi avasi muttei auennut!"); } } }
Pitäs aina muistaa asiayhteys, kun näitä värkkää. Meitin esimerkki näytti vain, että tila(kone) voidaan koodata muillakin taviolla kuin käyttämällä muuttujaa. Jos haluat telkkarin referensotoitavaksi objektiksi (=hyvin kapseloitu) esimerkkisi mukaan, niin toteuta telkkari tämän esitelmän:n viimeisen esimerkin mukaan.
Siinä olion tila(kone) on kapseloitu ja oliota voidaan käyttää normaalisti. Meitin esimerkki näyttää vain tuon tila(konee)n koodauksen, ei kapseliontia.
(Väittää aina väliin maintenancea tuolle linkille, joten ootellaan josko se esitelmä sieltä vielä ilmaantuisi)
Aihe on jo aika vanha, joten et voi enää vastata siihen.