NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 7 - Dědičnost a polymorfismus

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
David Novák
Tvůrce
Avatar
David Novák:28.9.2023 8:00

Ahoj Jaroslave, děkujeme za podnět, který jsem předal k řešení.

 
Odpovědět
28.9.2023 8:00
Avatar
slezak-petr
Člen
Avatar
slezak-petr:6.10.2023 9:25

Ahoj všem
mám třídu:

public class DataObjectMetaData
{
    public string Caption { get; set; }
    public string ClassName { get; set; }
    public List<Command> Commands { get; set; }
    public List<Field> Fields { get; set; }
    public List<Link> Links { get; set; }
}

public override string ToString()
{
    string text ="";

    text += "Caption: " + this.Caption + "\r\n";
    text += "ClassName: " + this.ClassName + "\r\n";
    // text += " ... " + "\r\n";

    return text;
}

a jde mi o class.ToString();

a to o tyto Listy<>

public List<Command> Commands { get; set; }
public List<Field> Fields { get; set; }
public List<Link> Links { get; set; }

Kde Command, Field a Link
mají inplementovanou metodu ToString()

Takže mi funguje toto:

foreach (Field f in Fields)
{
    text += "\t" + f.ToString() + "\r\n";
}

Ale já hledám cestu (dědičnost z?) jak to nedeklarovat ručně, ale nějak automaticky
našel jsem cestu přes GetProperties
ale jak získat objekt, abych s ním mohl pracovat jako s listem?

string text = "{";

foreach (var prop in type.GetProperties())
{
    string pName = prop.Name;
    var pValue = prop.GetValue(this, null);
    string pType = prop.PropertyType.ToString();
    bool bList = pType.StartsWith("System.Collections.Generic.List");


    if (!bList)
    {
        text += String.Format("Namespace: {5} {2}{0}{2}: {2}{1}{2} | Type is: {3} | Is list: {4}", pName, pValue, "\"", pType, bList, nmsp);
    }
    else
    {
        var objProp = type.GetProperty(pName);
        PropertyInfo info = type.GetProperty(pName);
        // **tady získat z objProp List<Field> Fields**
    }

    count++;
    if (count < totalCount) text += ", ";
    text += "\r\n";
}

text += "}";

Listů List<?> mám ve třídě asi sedm
a nejde mi o to udělat ručně sedmkrát foreach
ale spíš hledám správnou cestu, jak by se to mělo udělat

Odpovědět
6.10.2023 9:25
Čím víc se učím, tím víc mi přijde, že toho ještě mnoho neumím
Avatar
Pavel Sojka
Člen
Avatar
Pavel Sojka:29.12.2024 9:14

Polymorfismus nějak nemůžu pochopit...
123456786798

 
Odpovědět
29.12.2024 9:14
Avatar
Jan Ráž
Člen
Avatar
Odpovídá na slezak-petr
Jan Ráž:2. února 12:09

Ahoj, než jsem stihl kouknout na datum příspěvku, tak jsem si to otestoval. I když je to pro tebe asi pozdě, tady je dle mého vysvětlení:

Pro jednoduchý výpis listů jiných typů musíš vytvořit rodičovskou třídu od které oddědíš všechny typy, které chceš hezky vypisovat, pro názornost jsem vytvořil třídu Item:

internal class Item
{
    static int globalId = 0;

    protected string Nazev;
    protected string Popis;
    protected int Id;


    public Item(string nazev, string popis)
    {
        Nazev = nazev;
        Popis = popis;
        Id = globalId++;
    }

    public override string ToString()
    {
        return $"ID: '{Id}' Nazev: '{Nazev}' Popis: '{Popis}'";
    }
}

Ta má nějaké základní atributy a svůj přetížený výpis (ToString();)

Od ní jsem oddědil třídy Command a Field. (Pro příklad jsem nedělal třetí typ):
Command:

internal class Command : Item
{
    public DateTime ExpireDate;

    public Command(string nazev, string popis) : base(nazev, popis)
    {

    }

    public bool isExpired()
    {
        return ExpireDate < DateTime.Now;
    }

    public override string ToString()
    {
        return base.ToString() + $" ExpireDate: '{ExpireDate}'";
    }
}

a třída Field:

internal class Field : Item
{
    public string Type = "Default";
    protected bool IsEmpty = true;

    public Field(string nazev, string popis) : base(nazev, popis)
    {

    }

    public void Fill()
    {
        IsEmpty = false;
    }

    public override string ToString()
    {
        return base.ToString() + $" Type: '{Type}' IsEmpty: '{IsEmpty}'";
    }
}

Dále jsem upravil výpis ve třídě DataObjectMeta­Data:

internal class DataObjectMetaData
{
    public string Caption { get; set; }
    public string ClassName { get; set; }
    public List<Command> Commands { get; set; }
    public List<Field> Fields { get; set; }

    private string ListToString(List<Item> mujList)
    {
        string vypis = "";
        foreach (Item item in mujList)
        {
            vypis += item.ToString() + "\n";
        }
        return vypis;
    }

    public override string ToString()
    {
        string vypis = "";

        vypis += $"Caption: '{Caption}' ClassName: '{ClassName}'\n";
        vypis += "Commands:\n";
        vypis += ListToString(Commands.Cast<Item>().ToList());
        vypis += "Fields:\n";
        vypis += ListToString(Fields.Cast<Item>().ToList());
        return vypis;
    }
}

Kde jsem vytvořil metodu pro výpis čistě Listů itemů, tedy List<Item> mujList
a potom už zbývalo jen přetypovat daný list commandů a list fieldů na list rodičovské třídy tedy itemů: Nechal jsem si poradit a je to takto "Commands.Cas­t<Item>().ToLis­t()"

Pro vyzkoušení jsem už jen vytvořil testovací data:

static void Main(string[] args)
{
    DataObjectMetaData dataObjectMetaData = new DataObjectMetaData();
    dataObjectMetaData.Caption = "Můj speciální popisek";
    dataObjectMetaData.ClassName = "SuperJménoTřídy";
    dataObjectMetaData.Commands = new List<Command>();
    dataObjectMetaData.Fields = new List<Field>();


    // Vytvoření testovacích dat
    for (int i = 1; i <= 10; i++)
    {
        Command command = new Command($"MujPrikaz{i}", $"MujPopisekItemu{i}");
        command.ExpireDate = DateTime.Now.AddDays(i);
        dataObjectMetaData.Commands.Add(command);

        Field field = new Field($"MojePole{i}",$"MujPopisekPole{i}");
        field.Type += $" Generováno na pozici: {i}";
        if (i % 2 == 0)
        {
            field.Fill();
        }
        dataObjectMetaData.Fields.Add(field);

    }

    Console.WriteLine(dataObjectMetaData.ToString());

    Console.WriteLine("Konec");
    Console.ReadKey();
}

Po spuštění programu, ve kterém prakticky vytvořím jeden objekt typu DataObjectMeta­Data, naplním jej hodnotami a potom zavolám "Console.Write­Line(dataObjec­tMetaData.ToS­tring());" dostanu výsledek: viz obrázek.

Snad ti to pomohlo, nebo někomu jinému. Mimochodem, v této části kurzu se tohle asi nemá řešit :D

 
Odpovědět
2. února 12:09
Avatar
Jan Ráž
Člen
Avatar
Jan Ráž:2. února 12:14

Ahoj

Možná by se v této lekci vyplatilo říct, že jde již polymorfizmus používali při přepisování metody ToString: public override string ToString().

podle vlastní zkušenosti, každý kdo se o tomto děsivém názvu učí poprvé, tak si představuje složitosti jaderné fyziky :D

 
Odpovědět
2. února 12:14
Avatar
slezak-petr
Člen
Avatar
Odpovídá na Jan Ráž
slezak-petr:7. února 8:14

Děkuji už nevím co jsem řešil, ale díky za příklad
ještě se ujistím, že jednu část kódu chápu dopře:

internal class Command : Item
{
    public DateTime ExpireDate;

    public Command(string nazev, string popis) : base(nazev, popis) # "base" zastupuje rodiče, tedy
je to jako bych volal rodičovskou třídu: "Item(string nazev, string popis)"
    {

    }

Je to tak, rozumím tomu dobře?

Odpovědět
7. února 8:14
Čím víc se učím, tím víc mi přijde, že toho ještě mnoho neumím
Avatar
Jan Ráž
Člen
Avatar
Odpovídá na slezak-petr
Jan Ráž:7. února 8:20

Ano, vlastně konstruktor potomka místo zavolat i konstruktor rodiče. Proto se tam musí předat všechny potřebné parametry.

Stejně tak v zde:

internal class Command : Item
{
    public DateTime ExpireDate;

    public Command(string nazev, string popis) : base(nazev, popis)
    {

    }

    public bool isExpired()
    {
        return ExpireDate < DateTime.Now;
    }

    public override string ToString()
    {
        return base.ToString() + $" ExpireDate: '{ExpireDate}'";
    }
}

V metodě ToString se volá base.ToString(). Což začíná metodu ToString() na rodiči. Kdyby to tam nebylo, tak by měla ToString ve třídě potomka nahradila to rodičovskou. Takto ale říkáme, že chceme zachovat obě.

 
Odpovědět
7. února 8:20
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 47.