Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C#: Apua ominaisuuden kanssa C#

Sivun loppuun

uusiKoodaaja [03.02.2021 15:20:50]

#

Hei,

Saisinkohan apua tätä kautta? Opiskelutehtävässä pitää luoda Hinta-ominaisuus, joka laskee yli 30 ylittävän kirjan hintaa automaattisesti 10%. Alla nykyinen koodi. Ongelma on siinä, että sekä Hinta-ominaisuutta, että alkuperäistä hinta-parametriä käytetään pääohjelmassa.
Voisin toki jättää vain tämä tehtävän tekemättä ja mennä seuraavaan, mutta tulen hulluksi jos en saa tietää missä tein virheen..

using System;

class Kirja
{
    public string nimi;
    public string kirjailija;
    public string kustantaja;
	public string teema;
	public float hinta;
	private float _hinta;

	public Kirja(string nimi, string kirjailija, string kustantaja, float _hinta, string teema)
    {
        this.nimi = nimi;
        this.kirjailija = kirjailija;
        this.kustantaja = kustantaja;
        this.hinta = _hinta;
        this.teema = teema;
    }

	public float Hinta
	{
		get
		{
			return _hinta;
		}
		set
		{
			if (value > 30) {
				_hinta = value * 0.9f;
			} else {
				_hinta = value;
			}
		}
	}
}

class Program
{
//Tästä eteenpäin en voi muokata koodia
	static void Main(string[] args)
	{
		Kirja k = new Kirja("Kirja", "K. Kirjoittaja", "Kustannus Oy", 21.50f, "Dekkari");
		Kirja k2 = new Kirja("Toinen Kirja", "O. Kirjailija", "Kustantaja Ab", 36.90f, "Fantasia");

		Console.WriteLine(k.hinta);
		Console.WriteLine(k2.Hinta);
	}
}

Metabolix [03.02.2021 15:46:53]

#

Nyt sinulla on kaksi erillistä hintamuuttujaa (hinta ja _hinta), joista jälkimmäinen pitäisi asettaa Hinta-ominaisuuden kautta ja alennus tähän tapahtuisi asettamisen yhteydessä. Olio voi olla oudossa tilassa, kun hinta ja _hinta sisältävät aivan eri luvut. Nyt et edes aseta jälkimmäistä ollenkaan.

Tehtävässä varmaan tarkoitetaan, että luokalla olisi vain yksi ”public float hinta” (eli _hinta pitäisi ottaa pois) ja että Hinta-ominaisuus olisi vain luettavissa eli set-funktiota ei olisi ollenkaan ja get-funktiossa palautettaisiin ohjeen mukaan joko alkuperäinen tai alennettu hinta.

Ylipäänsä on äärettömän sekavaa käyttää noin samanlaisia nimiä (hinta, _hinta, Hinta) ja vieläpä niin, että sekä hinta että Hinta ovat julkiset. Oikeassa ohjelmassa nämä olisi järkevää nimetä hinnat sen mukaan, mitä ne oikeasti kuvaavat, esimerkiksi Normaalihinta ja Myyntihinta.

uusiKoodaaja [03.02.2021 16:50:53]

#

Epäilemättä on hankaluutta tuossa koodin pätkässä, mutta esim. nimet tehtävässä tuli annettuna, varmasti osittain senkin takia, että pitäisi osata tunnistaa erot melkein samoissa nimissä. Kiitos kommenteista, Metabolix!

Keksinkin ratkaisun kun ulkona kävellessä pyörittelin asiaa päässäni. Muokkasin muodostimen seuraavanlaiseksi, niin homma pelitti kuten pitää.

    public Kirja(string nimi, string kirjailija, string kustantaja, float Hinta, string teema)
	{
		this.nimi = nimi;
		this.kirjailija = kirjailija;
		this.kustantaja = kustantaja;
		this.hinta = Hinta;
		this.Hinta = Hinta;
		this.teema = teema;
    }

Metabolix [03.02.2021 17:24:58]

#

Vaikka ratkaisusi tässä tapauksessa toimii, se on silti periaatteellisesti väärä, koska tuossa olisi mahdollista asettaa ulkoa päin täysin eri arvo hintaan ja Hintaan ja lisäksi Hinta käyttäytyy oudosti niin, että esimerkiksi rivi Hinta = Hinta laskee arvoa 10%:lla:

k.Hinta = 5678;
k.hinta = 1234;
Console.WriteLine("{0} ja {1}", k.hinta, k.Hinta);
// 1234 ja 5110,2, eli arvot ovat erilliset eikä Hinta päivity itsestään.

k.Hinta = k.Hinta;
Console.WriteLine(k.Hinta); // 4599,18
k.Hinta = k.Hinta;
Console.WriteLine(k.Hinta); // 4139,262
k.Hinta = k.Hinta;
Console.WriteLine(k.Hinta); // 3725,335

Tämän takia loogisempi ja paremmin tehtävänantoa vastaava ratkaisu tehtävään olisi tuo kuvailemani, jossa alennus tehdään lukemisen yhteydessä.

public float Hinta {
  get {
    if (hinta > 30) {
      return 0.9f * hinta;
    }
    return hinta;
  }
}

// ...
// k.Hinta = 5678; // Mahdoton rivi, Hinta voidaan vain lukea.
k.hinta = 1234;
Console.WriteLine("{0} ja {1}", k.hinta, k.Hinta);
// 1234 ja 1110,6, eli Hinta lasketaan asetetun hinta-arvon mukaan.

Tehtävä on huolimattomasti suunniteltu: jos tehtävä tarkastetaan pelkästään tuolla antamallasi koodilla, siihen voisi lähettää ratkaisuksi jopa tämän:

public float Hinta = 0.9f * 36.90f;

uusiKoodaaja [04.02.2021 09:15:01]

#

Kieltämättä tuo koodi on aika huono, jos kyseessä olisi oikea ohjelma. Tuo pääohjelma kuitenkin rajoittaa minua ja nimet on varmasti tahallaan valittu sekavasti.
Minulle kuitenkin jäi vielä epäselväksi voiko hinta-parametriä käyttää sekä ominaisuuden taustalla että olioiden parametrinä itsessään? Ei ainakaan niin kauan kuin se on private, mitä vaaditaan ominaisuudelle. Kysymys kuuluu siis, että voinko pääohjelmassa jotenkin määrittää että tarkistetaanko onko hinta yli 30 vai en käyttämällä joko hinta- tai Hinta-muotoa?

Metabolix [04.02.2021 09:23:45]

#

Ominaisuus ei vaadi yksityistä (private) jäsentä tai ylipäänsä mitään muutakaan, oikeastaan get- ja set-funktioihin voi kirjoittaa melkein mitä tahansa. Eli kyllä, voit käyttää samaa julkista hinta-jäsentä ja ominaisuudessa palauttaa siitä alennetun hinnan. Yllä juuri esitin tähän sopivan Hinta-ominaisuuden. (Parametri tarkoittaa funktion suluissa määriteltyä muuttujaa, taisit sekoittaa termejä.)

Kurssilla ehkä neuvotaan käyttämään yksityistä jäsentä siksi, että usein ominaisuuden tarkoitus on juuri rajoittaa jäsenen käyttöä jotenkin ja silloin ei ole järkevää samaan aikaan antaa vapaata pääsyä jäseneen toisella nimellä. Esimerkiksi jos Hinta-ominaisuus hyväksyisi vain lukuja 0-1000, olisi väärin sallia toista kautta arvon muokkaus mielivaltaisesti.

The Alchemist [04.02.2021 09:30:37]

#

uusiKoodaaja kirjoitti:

Kieltämättä tuo koodi on aika huono, jos kyseessä olisi oikea ohjelma. Tuo pääohjelma kuitenkin rajoittaa minua ja nimet on varmasti tahallaan valittu sekavasti.

Ei kannata kuvitella liikoja kurssinvetäjän omista taidoista ja huolellisuudesta. Kyseessä on tahaton typo, kirjoitusvirhe. Ja vaikka se olisi tarkoituksellinen suunnittelumoka, niin se olisi niin typerä virhe, että sinä voit koodarina korjata sen oma-aloitteisesti.

(Paitsi jos tehtävät tarkastetaan käyttäen jotain automatisoitua systeemiä, joka ehdottomasti vaatii tuollaiset nimet, jotta oman tehtävän saisi menemään läpi.)

Järkevintä olisi toki ottaa yhteyttä opettajaan ja kysyä, että miksi tehtävä vaikuttaa virheelliseltä.

Grez [04.02.2021 09:43:25]

#

Oonko ainoa jota häiritsee pahasti, että hinnan tietotyyppi on float?

vesikuusi [04.02.2021 21:49:12]

#

Grez kirjoitti:

Oonko ainoa jota häiritsee pahasti, että hinnan tietotyyppi on float?

Koulutehtävien "harmittomista" oikoteistä tulee kaupallisen softan kulmakiviä. Kuka olisi uskonut että ihmiset oppivat esimerkistä? Tässäkin tapauksessa opettaja olisi voinut välttää aiheuttamasta epäsuoran kymmenvuotisen teknisen velan maailman ohjelmistokehitykselle käyttämällä vaikka int-tietotyyppiä ja senttejä.

Customer extends Person jne. koska asiakashan on henkilö??

Metabolix [04.02.2021 22:25:17]

#

vesikuusi kirjoitti:

– – int-tietotyyppiä ja senttejä.

C# sisältää decimal-tietotyypin, joka on nimenomaan kymmenjärjestelmään sopiva liukuluku, toisin kuin binäärijärjestelmässä toimiva float. Decimal-tyyppiä kannattaisi käyttää esimerkiksi juuri hintojen yhteydessä. Lukuarvon voi merkitä decimal-tyyppiseksi m-kirjaimella, esimerkiksi 0.9m.

vesikuusi [05.02.2021 01:12:58]

#

Metabolix kirjoitti:

(04.02.2021 22:25:17): ”– –” C# sisältää decimal-tietotyypin, joka on...

Totta turiset. On se terävä kieli!

Grez [05.02.2021 08:16:18]

#

Sinänsähän käsittääkseni Excel käyttää laskemiseen 64-bittisiä liukuluja, ja monet käyttää Exceliä raha-asioiden laskemiseen. Float on kuitenkin 32-bittinen liukuluku (vain 6-9 merkitsevää numeroa.)

Itse käyttäisin tosiaan decimal tietotyyppiä (joka on 128-bittinen liukuluku jonka kertoimen kanta on 10, eikä 2 kuten float:lla ja doublella). Mutta jos nyt haluaa prosessorin suoraan ymmärtämiä liukuluja käyttää, niin C#:ssa olisi myös double, joten sikälikin float on aika käsittämätön.

Toki jos seuraavana harjoituksena on huomata floatin ongelmat ja siirtyä johonkin järkevämpään, niin mikäs siinä.

neosofta [21.03.2021 16:55:43]

#

Ciao uusiKoodaaja!

using System;

class Kirja
{
    public string nimi;
    public string kirjailija;
    public string kustantaja;
    public string teema;
    public float hinta;
    private float _hinta;

    public Kirja(string nimi, string kirjailija, string kustantaja, float _hinta, string teema)
    {
        this.nimi = nimi;
        this.kirjailija = kirjailija;
        this.kustantaja = kustantaja;
        Hinta = _hinta; //asetetaan parametrin arvolla -> (set)
        this.hinta = Hinta; //asetetaan julkisen muuttujan arvoksi <- (get)
        this.teema = teema;
    }

    public float Hinta
    {
        get
        {
            return _hinta > 30 ? _hinta * 0.9f : _hinta;
        }
        set
        {
            _hinta = value;
        }
    }
}
class Program
{
//Tästä eteenpäin en voi muokata koodia
	static void Main(string[] args)
	{
		Kirja k = new Kirja("Kirja", "K. Kirjoittaja", "Kustannus Oy", 21.50f, "Dekkari");
		Kirja k2 = new Kirja("Toinen Kirja", "O. Kirjailija", "Kustantaja Ab", 36.90f, "Fantasia");

		Console.WriteLine(k.hinta); //mieti mistä arvo haetaan tässä
		Console.WriteLine(k2.Hinta); //ja miten arvo haetaan tässä
	}
}

Tarkoituksella kinkkiseksi muotoiltu tehtävä, pistää miettimään 😊

Metabolix [25.03.2021 10:44:34]

#

Howdy ho, Neau33 v2.0?

Mitään kinkkistä ei ole tässä. Samaa tietoa ei kannata sentään tallentaa kahteen kertaan vain sen takia, että tehtävässä halutaan hakea se kahdella tavalla.

class Kirja {
    public float hinta;

    public Kirja(float _hinta) {
        hinta = _hinta;
    }

    public float Hinta {
        get {
            return hinta > 30 ? hinta * 0.9f : hinta;
        }
    }
}

neosofta [25.03.2021 15:01:03]

#

Howdy Meta(A)?

You almost figured it out, so 9.95 points for that!
But, when talking about coders there's one tiny little thing that makes you wonder if your version number increases or decreases when you're getting older. That's the main question.
What I do think my version number is something 0.2 nowadays and it keeps on going down.

Well, on my retirement days I just got a little excited again.😃

neosofta [25.03.2021 15:58:40]

#

Metabolix kirjoitti:

class Kirja {
    public float hinta;

    public Kirja(float _hinta) {
        hinta = _hinta;
    }

    public float Hinta {
        get {
            return hinta > 30 ? hinta * 0.9f : hinta;
        }
    }
}

Varsin eleganttia...


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta