Helsingin yliopisto > Tietojenkäsittelytieteen laitos > Ohjelmointitekniikka (Java) -opintojakso keväällä 2005

Koetehtävän 2 arvostelukertomus

Tehtävä

  1. Käyttöliittymäelementteihin liitetään tapahtumankuuntelijoita, jotka perinteisesti ohjelmoidaan toteuttamalla jokin tietty rajapintaluokka, esimerkiksi MouseListener. Tapahtumankuuntelijan voi ohjelmoida myös käyttäen sopivaa adapteriluokkaa, esimerkiksi MouseAdapter. Miten adapteriluokkaa käytetään tapahtumankuuntelijan toteuttamisessa ja mitä hyötyä adapteriluokan käyttämisestä voi olla verrattuna rajapintaluokan toteuttamiseen?
  2. Voiko sama olio kuunnella useammantyyppisiä tapahtumia (esimerkiksi tietyn painikkeen painamista ja tietyn valintaruudun valitsemista)? Voiko samantyyppistä tapahtumaa (esimerkiksi tietyn painikkeen painamista) kuunnella useampi olio? Perustele molemmat vastauksesi. Jos voi, miten se toteutetaan? Jos ei voi, miksi se on mahdotonta?
  3. Miksi pitkään kestävien asioiden tekeminen tapahtumankuuntelijassa "hyydyttää" käyttöliittymän, toisin sanoen käyttöliittymä ei vaikuta reagoivan esimerkiksi painikkeiden painamiseen?
  4. Oheisen koodin tarkoitus on näyttää ikkuna, jossa on tekstiä. Koodi kääntyy ilman virheitä, mutta suoritettaessa koodi ei tee mitä sen on tarkoitus tehdä. Miksei?
    import javax.swing.*;
    public class Test {
        public static void main(String[] args) {
            JFrame frame = new JFrame("My Demo Frame");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JLabel label = new JLabel("My Demo Text");
        }
    }

Esimerkkivastaus

Adapteriluokkaa hyödynnetään tapahtumankuuntelijan toteuttamisessa tekemällä omasta tapahtumakuuntelijaluokasta adapteriluokan aliluokka. Koska adapteriluokka sisältää tyhjät toteutukset kaikille rajapintaluokan vaatimille metodeille, voimme omassa tapahtumakuuntelijaluokassamme syrjäyttää vain ne metodit, joista olemme kiinnostuneita.

Sama olio voi kuunnella useammantyyppisiä tapahtumia: ohjelmoidaan olion luokka toteuttamaan kaikkien haluttujen tapahtumien vaatimat rajapintaluokat. Samantyyppistä tapahtumaa voi kuunnella useampi olio: rekisteröidään kukin olio halutun tapahtuman kuuntelijaksi kutsumalla komponentin addXxxxxListener-metodia.

Kaikkien tapahtumakuuntelijoiden kutsut suoritetaan samassa säikeessä. Jos yhdessä tapahtumakuuntelijassa viivytään pitkään, tuona aikana käyttöliittymän käyttämisestä aiheutuvia tapahtumia ei voida käsitellä.

Luotu JLabel olisi lisättävä luotuun JFrameen (tarkemmin sanottuna sen content paneen) ja lisäksi JFrame olisi asetettava näkyväksi asianmukaista metodia (setVisible()) kutsuen.

Pisteytys

Tehtävästä sai yhteensä enintään seitsemän pistettä.

Adapteriluokkaa hyödynnetään tapahtumankuuntelijan toteuttamisessa tekemällä omasta tapahtumakuuntelijaluokasta adapteriluokan aliluokka. Koska adapteriluokka sisältää tyhjät toteutukset kaikille rajapintaluokan vaatimille metodeille, voimme omassa tapahtumakuuntelijaluokassamme syrjäyttää vain ne metodit, joista olemme kiinnostuneita.

Vastauksesta sai enintään kaksi pistettä: toisen selittämällä periyttämisen, toisen selittämällä saavutettavan hyödyn. Pelkkää koodiesimerkkiä adapteriluokan käyttämisestä nimettömän sisäluokan ilmentymää luotaessa ei pidetty riittävänä selityksenä periyttämisestä.

Sama olio voi kuunnella useammantyyppisiä tapahtumia: ohjelmoidaan olion luokka toteuttamaan kaikkien haluttujen tapahtumien vaatimat rajapintaluokat. Samantyyppistä tapahtumaa voi kuunnella useampi olio: rekisteröidään kukin olio halutun tapahtuman kuuntelijaksi kutsumalla komponentin addXxxxxListener-metodia.

Vastauksesta sai enintään kaksi pistettä: yhden kummastakin oikeasta, oikein perustellusta vastauksesta.

Jotkut perustelivat saman olion voivan kuunnella useammantyyppisiä tapahtumia siksi, että tuon olion luokka voi toteuttaa ActionListener-rajapinnan ja useat erityyppiset komponentit (esimerkiksi JButton, JMenuItem ja JCheckBox) hyväksyvät kuuntelijakseen ActionListener-tyyppisen olion. Tätä ei kysymyksellä varsinaisesti haettu, mutta kysymys oli helposti tulkittavissa tälläkin tavalla, joten perustelu hyväksyttiin.

Jotkut väittivät, että samantyyppistä tapahtumaa (esimerkiksi tietyn painikkeen painamista) voi kuunnella vain yksi olio kerrallaan, mutta tilanne voidaan kiertää siten, että tuo yksi olio välittää tiedon useammille olioille. Tätä perustelua ei hyväksytty, sillä väite on alkuosaltaan virheellinen eivätkä tapahtumatietoja välittäjän kautta vastaanottavat oliot ole kuuntelijoita siinä merkityksessä kuin kuuntelija-käsitettä Swingistä puhuttaessa käytetään.

Kaikkien tapahtumakuuntelijoiden kutsut suoritetaan samassa säikeessä. Jos yhdessä tapahtumakuuntelijassa viivytään pitkään, tuona aikana käyttöliittymän käyttämisestä aiheutuvia tapahtumia ei voida käsitellä.

Vastauksesta sai enintään yhden pisteen. Vastauksessa oli eksplisiittisesti mainittava syyksi yhden säikeen käyttäminen. Jos vastaus ei viitannut yhteen säikeeseen, se oli yleensä tyyppiä "pitkään kestävät asiat tehdään ensin loppuun", mikä on lähinnä kysymyksen uudelleenmuotoilu.

Luotu JLabel olisi lisättävä luotuun JFrameen (tarkemmin sanottuna sen content paneen) ja lisäksi JFrame olisi asetettava näkyväksi asianmukaista metodia (setVisible()) kutsuen.

Vastauksesta sai enintään kaksi pistettä: yhden pisteen JLabelin lisäämisestä ja yhden pisteen JFramen näkyväksi asettamisesta. Koodia ei pisteiden saamiseksi tarvinnut kirjoittaa eikä koodin virheistä sakotettu: riitti että ongelmien huomaaminen kävi vastauksesta ilmi.

On olemassa muitakin kuin esimerkkivastauksessa kerrottuja tapoja saada koodi toimimaan. Kaikki tavat hyväksyttiin.

Pisteiden jakauma

Pisteiden keskiarvoksi muodostui 4,9.

Taulukko 1. Pisteiden jakauma
yhteispisteet vastausten lukumäärä
7 xxxxxxxxxx
6 xxxxxxxxxxxxxxxx
5 xxxxxxxxxxxxx
4 xxxxxxx
3 xxxx
2 xxxxx
1 xxx
0