TlačiťTlačiť Slovenčina English Hľadať RSS

© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 16. 4. 2024.

Stránka sa načítava, prosím čakajte…

Dátum: 19. 4. 2020, pred štyrmi rokmi

Všetky „základné“ objekty (objekty, ktoré sú ekvivalentmi primitívnych údajových typov, objekty typu String a ďalšie) sú „nemeniteľné“/nemenné (immutable), to znamená, že po ich úplnom vytvorení už nie je možné meniť ich hodnotu. Java sa tiež bráni parametrom odovzdávaným podľa referencie (passing by reference), čím zamedzuje „popleteniu“ (hodnôt) argumentov po návrate z volania metódy (čo býva inak relatívne častá chyba a je to zdroj potenciálnych problémov). Prináša to aj isté nevýhody, ale v zásade je tento prístup správny.

„Obídeniu“ obidvoch týchto „problémov“ sa venuje tento článok, pričom smeruje od najjednoduchšieho riešenia ku kvázi „najsprávnejšiemu“ – z pohľadu princípu uzavretosti OOP. Princíp je všade rovnaký – definovať triedu reálneho čísla, ktorá nie je nemenná a na demonštráciu jednu metódu vymieňajúcu hodnoty dvoch inštancií tejto triedy.

Tým je porušený jeden zo základných princípov Javy, ale v prípade výskytu v praxi by nemusela byť situácia kritická, keby si všetci členovia tímu boli vedomí tejto vlastnosti triedy a používali ju výhradne týmto spôsobom. (Myslím si však, že benefit by bol malý. Situácia sa dá riešiť aj inak.) Príklad je aspoň jednoduchou ukážkou ukazujúcou (postupne sa rozvíjajúc) princíp uzavretosti OOP.

~

// Minimálna verzia – vnútorný objekt nemá konštruktor, ani getter/setter
// („čítač“/„nastavovač“) atribútu.
// Z pohľadu OOP „najmenej správne.“ (Z pohľadu dľžky kódu najkratšie.)

public class VymeňReálne
{
	public class ReálneČíslo
	{
		public double hodnota = 0.0;
	}

	public VymeňReálne()
	{
		ReálneČíslo číslo1 = new ReálneČíslo();
		ReálneČíslo číslo2 = new ReálneČíslo();

		číslo1.hodnota = 10;
		číslo2.hodnota = 16;

		vymeň(číslo1, číslo2);

		System.out.println("číslo1: " + číslo1.hodnota);
		System.out.println("číslo2: " + číslo2.hodnota);
	}

	public void vymeň(ReálneČíslo a, ReálneČíslo b)
	{
		double c = a.hodnota;
		a.hodnota = b.hodnota;
		b.hodnota = c;
	}

	public static void main(String[] args)
	{
		new VymeňReálne();
	}
}

~

// Verzia s úplným konštruktorom (full constructor) vnútornej triedy.
// Síce odbudli riadky „ručne“ nastavujúce hodnoty objektov, ale celkovo
// sa počet riadkov zvýšil (čo by sa dalo redukovať pri inej konvencii
// zápisu). Tak, či onak, z pohľadu OOP je tento prístup správnejší.

public class VymeňReálne
{
	public class ReálneČíslo
	{
		public double hodnota;

		public ReálneČíslo(double počiatočnáHodnota)
		{
			hodnota = počiatočnáHodnota;
		}
	}

	public VymeňReálne()
	{
		ReálneČíslo číslo1 = new ReálneČíslo(10);
		ReálneČíslo číslo2 = new ReálneČíslo(16);

		vymeň(číslo1, číslo2);

		System.out.println("číslo1: " + číslo1.hodnota);
		System.out.println("číslo2: " + číslo2.hodnota);
	}

	public void vymeň(ReálneČíslo a, ReálneČíslo b)
	{
		double c = a.hodnota;
		a.hodnota = b.hodnota;
		b.hodnota = c;
	}

	public static void main(String[] args)
	{
		new VymeňReálne();
	}
}

~

// Verzia s getterom a setterom („čítačom“ a „nastavovačom“) súkromného
// atribútu. Z pohľadu OOP správne, ale chýba tu možnosť nastavenia hodnoty
// priamo počas konštrukcie. (Akoby kompromis predchádzajúcich dvoch verzií.)

public class VymeňReálne
{
	public class ReálneČíslo
	{
		private double hodnota = 0.0;

		public void zapíš(double nováHodnota)
		{
			hodnota = nováHodnota;
		}

		public double čítaj()
		{
			return hodnota;
		}
	}

	public VymeňReálne()
	{
		ReálneČíslo číslo1 = new ReálneČíslo();
		ReálneČíslo číslo2 = new ReálneČíslo();

		číslo1.zapíš(10);
		číslo2.zapíš(16));

		vymeň(číslo1, číslo2);

		System.out.println("číslo1: " + číslo1.čítaj());
		System.out.println("číslo2: " + číslo2.čítaj());
	}

	public void vymeň(ReálneČíslo a, ReálneČíslo b)
	{
		double c = a.čítaj();
		a.zapíš(b.čítaj());
		b.zapíš(c);
	}

	public static void main(String[] args)
	{
		new VymeňReálne();
	}
}

~

// Verzia so všetkým dohromady… (Najdlší kód, ale z pohľadu OOP princípov
// „najsprávnejšie.“)

public class VymeňReálne
{
	public class ReálneČíslo
	{
		private double hodnota;

		public ReálneČíslo(double počiatočnáHodnota)
		{
			hodnota = počiatočnáHodnota;
		}

		public void zapíš(double nováHodnota)
		{
			hodnota = nováHodnota;
		}

		public double čítaj()
		{
			return hodnota;
		}
	}

	public VymeňReálne()
	{
		ReálneČíslo číslo1 = new ReálneČíslo(10);
		ReálneČíslo číslo2 = new ReálneČíslo(16);

		vymeň(číslo1, číslo2);

		System.out.println("číslo1: " + číslo1.čítaj());
		System.out.println("číslo2: " + číslo2.čítaj());
	}

	public void vymeň(ReálneČíslo a, ReálneČíslo b)
	{
		double c = a.čítaj();
		a.zapíš(b.čítaj());
		b.zapíš(c);
	}

	public static void main(String[] args)
	{
		new VymeňReálne();
	}
}