OOP prakticky: Substituce

Jak budeme provádět substituci? Jednoduše, musíme v našem výrazu najít všechny proměnné stejného názvu a namísto těchto proměnných vrátit výraz, který je má nahradit. V podstatě na tom nic není. Ještě jedna otázka: budou mít metodu substituce všechny třídy? Vždyť substituovat budeme pouze proměnnou, takže by to svádělo k tomu napsat tuto metodu pouze semka. To by samozřejmě byla chyba. Pokud máme Proměnnou v Součtu, je jasné, že i tato Proměnná musí být nahrazena. Aby tato Proměnná mohla být nahrazena, musíme tu Proměnnou nejprve najít. To uděláme nejjednodušeji tak, že zavoláme metodu Substituce() u Součtu a ta zavolá metodu Substituce() jak na výraz A, tak na výraz B. Tím dosáhneme toho, že ať budeme třeba stovky zanořených Součtů, nakonec se dostaneme ke všech výrazům a všechny zkontrolujeme, jestli se náhodou nejedná o Proměnnou, kterou hledáme. Takže odpověď na původní otázku zní, že metodu Substituce() bude mít každý Matematický Výraz. Tam ji také definujeme.

1
2
3
4
5
6
{
public abstract MatematickyVyraz Derivace();
public abstract MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota);
public abstract MatematickyVyraz Kopie();

}

Metoda bude mít dva argumenty: String reprezentující Název Proměnné, kterou hledáme a Matematický Výraz, kterým chceme nahrazovat. Implementace v jednotlivých třídách již bude triviální. Připomínám, že metoda bude vracet nový Matematický Výraz, takže v každém kroku musím vytvářet nové kopie objektů. Konstanta:

1
2
3
4
public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)
{
return Kopie();
}

Konstantu zřejmě nijak substituovat nemůžeme, vrátíme proto pouze kopii. Implementace v Proměnné:

1
2
3
4
5
6
7
8
public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)
{
if(Nazev == NazevPromenne)
return Hodnota;
else
return Kopie();

}

Nejprve zjistíme, jestli jsme našli proměnnou, kterou hledáme. Pokud ano, vrátíme předaný Matematický Výraz. Pokud ne, vrátíme také pouze kopii Proměnné. U Binárních výrazů bude situace stejná – vytvoříme vždy novou instanci daného výrazu a na vlastnosti A a B poštveme substituci. Implementace u Součtu:

1
2
3
4
5
6
7
8
public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)

{
Soucet soucet = new Soucet();
soucet.A = A.Substituce(NazevPromenne, Hodnota);
soucet.B = B.Substituce(NazevPromenne, Hodnota);
return soucet;
}

Rozdíl:

public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)

1
2
3
4
5
6
{
Rozdil rozdil = new Rozdil();
rozdil.A = A.Substituce(NazevPromenne, Hodnota);
rozdil.B = B.Substituce(NazevPromenne, Hodnota);
return rozdil;
}

Součin:

public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)

1
2
3
4
5
6
{
Soucin soucin = new Soucin();
soucin.A = A.Substituce(NazevPromenne, Hodnota);
soucin.B = B.Substituce(NazevPromenne, Hodnota);
return soucin;
}

Podíl:

public override MatematickyVyraz Substituce(string NazevPromenne, MatematickyVyraz Hodnota)

1
2
3
4
5
6
{
Podil podil = new Podil();
podil.A = A.Substituce(NazevPromenne, Hodnota);
podil.B = B.Substituce(NazevPromenne, Hodnota);
return podil;
}

A to je všechno. Vyzkoušíme.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static void Main(string[] args)
{
Konstanta a = new Konstanta(10);
Konstanta b = new Konstanta(20);
Promenna x = new Promenna("x");
Promenna y = new Promenna("y");
Soucet soucet = new Soucet(a, x);
Soucin soucin = new Soucin(b, y);
Rozdil rozdil = new Rozdil(soucet, soucin);
Console.WriteLine("Před substitucí: {0}",
rozdil.ToString());

Console.WriteLine("Po substituci [x => 666]: {0}",
rozdil.Substituce("x", new Konstanta(666)).ToString());

Console.WriteLine("Po substituci [x => 666; y => 33]: {0}",
rozdil.Substituce("x", new Konstanta(666)).Substituce("y", new Konstanta(33)).ToString());

Console.WriteLine("Po substituce [x => (10 + 20)]: {0}",
rozdil.Substituce("x", new Soucet(a, b)).ToString());

Console.Read();

/*

Výstup z programu:
Před substitucí: ((10 + x) - (20 \* y))
Po substituci [x => 666]: ((10 + 666) - (20 \* y))
Po substituci [x => 666; y => 33]: ((10 + 666) - (20 \* 33))
Po substituce [x => (10 + 20)]: ((10 + (10 + 20)) - (20 \* y))
*/

}