logi sisse meist KKK

Küsimused puudutavad OOP mentaliteeti ja klasside kasutamist.

Probleem on järgmine:

Ma tahan teha üldise abstraktse klassi Aeg ja alamklassid Tund, Minut, Sekund. Klassis on float-tüüpi väli aeg. Näiteks:

Tund tund=new Tund();
tund.aeg=0.5; //pool tundi

Oletame, et ma tahan ajaühikud omavahel teisendada.

Selle jaoks on klassis Aeg float-tüüpi väli kordaja, mis ütleb igas Aja alamklassi (Tund, Minut, Sekund), mitu sekundit see ajaühik pikk on. Siin tekib esimene probleem. Ma tahaks seda muutujat kordaja teha kuidagi abstraktseks, et kordaja küsimisel pöördutaks alati alamklassi poole, sest klassis Aeg on kordaja väärtustamata.

Nii. Tahan teha meetodit public Aeg teisenda(Aeg alg, Class klass), mis teisendab Aja alg klass-tüüpi Ajaks.

Kuidas teha meetodit teisenda? Ma sain töötava prototüübi valmis, aga tahaks teada, kas saab ka teisiti. Siin on variandid, mida ma proovisin:

Variant 1)

public Aeg teisenda(Aeg alg, Class<?> klass) {
   Aeg l6pp=(Aeg)klass.newInstance(); //kas nii on ilus?
   l6pp.aeg=alg.aeg * alg.kordaja / l6pp.kordaja;
   return l6pp;
}

klass määrab ära, kuhu Class'i teisendada tuleb. klass peab meetodi kutsumisel olema kindlasti Aeg alamtüüp. Probleem tekkis selles, et ta võtab nüüd muutuja l6pp klassiks Aeg, ning isegi, kui mul on defineeritud klassis Minut kordaja=60, siis ta küsib ikkagi kordaja-t klassist Aeg. Tahaks selle kuidagi abstraktseks teha klassis Aeg.

Variant 2)

public Aeg teisenda(Aeg alg, Aeg l6pp) {
   l6pp.aeg=alg.aeg * alg.kordaja / l6pp.kordaja;
   return l6pp;
}

Kuidas kõige parem oleks?

küsitud Feb 18 '10 at 00:11

Rauni's gravatar image

Rauni
3113

edited Feb 18 '10 at 10:42

Rene%20Saarsoo's gravatar image

Rene Saarsoo ♦♦
1.1k101121

Muutsin pealkirja ära... "Küsimusi Java kohta" on liiga üldine.

(Feb 18 '10 at 10:44) Rene Saarsoo ♦♦

Üldiselt võiks see teisendusmeetod olla isendimeetod, esimeseks parameetriks on ju niikuinii mingi ajahulga isend??? Saaks kliendikoodi ilusamaks. Näite tegin siiski staatilise meetodiga.

abstract class Aeg {

    private float aeg;
    abstract float getKordaja();

    public static <T extends Aeg> T teisenda(Aeg alg, Class<T> tulem) {
        try {
            T tulemus = (T) tulem.newInstance();
            tulemus.setAeg(
                    alg.getAeg() * alg.getKordaja() / tulemus.getKordaja());
            return tulemus;
        } catch (InstantiationException e) {
            throw new RuntimeException("Veasõnum...", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Veasõnum...", e);
        }
    }

    public float getAeg() {
        return aeg;
    }

    public void setAeg(float aeg) {
        this.aeg = aeg;
    }
}

class Minut extends Aeg {

    @Override
    float getKordaja() {
        return 60F;
    }
}

class Tund extends Aeg {

    @Override
    float getKordaja() {
        return 3600F;
    }
}
link

vastatud Feb 18 '10 at 09:37

Samuel%20Paal's gravatar image

Samuel Paal
862

edited Feb 18 '10 at 10:29

Rene%20Saarsoo's gravatar image

Rene Saarsoo ♦♦
1.1k101121

Aitäh! See on täpselt see, mida ma tahtsin.

<t extends="" aeg="">. Kuidas see töötab? Ma saan aru, et see määrab T kuidagi olema Aeg alamklass selle meetodi piires, aga kas see ütleb siis täpselt ära, mis tüüpi klass T on? Või ütleb selle ära Class<t>, mis määrab meetodi konkreetsel väljakutsel T? Huvitav .. mis rakendusi sellisel süntaksil veel on?

(Feb 20 '10 at 15:20) Rauni

Enamasti oleneb õige lahendus sellest kuidas sa lõpptulemust kasutada tahad.

Antud juhul tekib mul koheselt küsimus, milleks on sul tarvis igale ajaühikule eraldi klassi? Enamasti lahendatakse ajaühikute teisendamine hoopis nõnda, et on üksainus aja klass, mis hoiab endas sisemiselt aega näiteks sekundites ning millel on meetodid küsimaks aja esitust tundides, minutites jne, sest mis need muud on kui lihtsalt selle sama aja esitusviisid. Nõndaviisi on lihtsam ka ajaobjekte omavahel võrrelda ja kõiksugu muid tehteid teha.

link

vastatud Feb 18 '10 at 10:41

Rene%20Saarsoo's gravatar image

Rene Saarsoo ♦♦
1.1k101121

Põhjus on selles, et mul on tegemist erinevate ühikute, nii aja- kui ka pikkusühikutega, ja ma tahtsin, et oleks võimalik neid käsitleda ühe objektina, kuid vajadusel ka eristada (ehk teatud kohtadest hoida lihtsalt muutujat tüüpi Ühik, teatud kohtades tüüpi ÜhikPikkus, teatud kohas teha uus muutuja tüübiga ÜhikMeeter.). Samuti on vaja teatud kohas lugeda sisse ühik failist ja see teisendada. Meetri ja minuti lugemisel on erinevus, sest 2.30 tähendab 2 meetrit ja 30 cm = 2.30m, aga 2 minutit ja 30 sekundit = 2.5 minutit. Samuti oli mulle oluline, et pärast oleks lihtne uusi ühikuid lisada.

(Feb 20 '10 at 14:56) Rauni

See OOP lahendus ei ole minu arust hetkel kõige parem. Peamine probleem selles, et tekib väga palju klasse, millest enamus teevad samu asju välja arvatud mõned parameetrid.

Minu arust parem lahendus oleks üldine klass stiilis (NB! kood testimata):

class Unit {
    private string unitClass;
    private float unitMultiplier;
    private string name;

    public static bool canConvert(Unit to){
        return unitClass == to.getUnitClass();
    }

    public float convert(float value, Unit to) {
        if ( canConvert(to) ){
            return value * unitMultiplier / to.getUnitMultiplier();
        }
        else{
            throw new RuntimeException("Do not try again...");
        }
    }

    public string getUnitClass(){
        return unitClass;
    }

    public float getUnitMultiplier(){
        return unitMultiplier;
    }

    public string getName(){
        return name;
    }

    public Unit(string aName,string aUnitClass, float aUnitMultiplier){
        unitClass = aUnitClass;
        unitMultiplier = aUnitMultiplier;
        name = aName;
    }
}

ja konfiguratsiooni fail stiilis:

time:milliseconds   :0.001
time:seconds        :1.0
time:minute         :60.0
time:hour           :3600.0

length:millimeter   :0.001
length:centimeter   :0.01
length:meter        :1.0

loed konf. faili sisse ning genereerid iga asja jaoks eraldi Unit-i. Kui teisendamisel on vaja mingisuguseid eraldi trikke ( näiteks Fahrenheit ja Celsius ), siis tekitad uue klassi Unit-st mis kirjutab üle convert meetodi ning lisad enda Unitite listi tekitamisel nö. käsitsi.

Võid siit sellise lahenduse kohta natuke veel lugeda.

link

vastatud Feb 23 '10 at 19:17

egon's gravatar image

egon ♦♦
771239

edited Feb 23 '10 at 19:22

Sul on õigus.

Ainult üks mõttekas põhjus on jäänud, miks kasutada iga ühiku jaoks erinevat klassi: mul on iga ühiku jaoks erinev andmete sisselugemisekood, kuna sisendandmete fail on kujul:

(meeter) 4.15 (sentimeeter) 4.10 (minut) 4.12.08

iga ühiku sisselugemisel on tähendus erinev: (min) 4.07.50 = 4 min 7.5 s, mis tuleb teisendada 4.125 minutiks. (m) 4.07.50 = 4 m 7.5 cm, mis on teisendatuna 4.075 meetrit.

Aga ka siin tuleks vist läheneda nii, et igale ühikule tuleks defineerida alamühik ja siis tuleks kogu kood ilusam.

Ma lugesin läbi su antud lingi (küll natuke kiirustades, aga siiski)

(Mar 04 '10 at 10:04) Rauni

Igal juhul aitäh kommentaari eest!

(Mar 04 '10 at 10:04) Rauni

kui sul on üldiselt sarnane struktuur sisselugemisel, siis saad neile juurde kirjutada formaatimise.

Üks võimalus selle jaoks on:

minute.second.centisecond -> minutes

Ja vastavat formaati sisse lugedes, siis selle jaoks teed kolm floati igaüks oma formaadiga. Ja lõpptulemuse saad minute.convert(a,minute) + second.convert(b,minute) + centisecond.convert(a,minute).

Aga üldiselt on arvatavasti lihtsam, kui sa sisselugemise jaoks kasutad eraldi koodi. Ning pärast kui oled sisselugenud saad kasutada neid objekte.

(Mar 04 '10 at 14:21) egon ♦♦
Sinu vastus
lülita eelvaade

Jälgi seda küsimust

By Email:

Pärast sisselogimist saad tellida muudatuse teavitusi siit

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *kaldkiri* või __kaldkiri__
  • **paks kiri** või __paks kiri__
  • link:[tekst](http://url.com/ "pealkiri")
  • pilt?![alt tekst](/path/img.jpg "pealkiri")
  • nummerdatud nimekiri: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • põhilised HTML märgendid on samuti toetatud

Pinu tööpakkumised

kõik pakkumised »

Küsimuse sildid:

×16
×5

küsitud: Feb 18 '10 at 00:11

nähtud: 3,379 korda

viimati uuendatud: Feb 23 '10 at 19:22

Litsents: Creative Commons Attribution License | Kontakt: info@pinu.ee