Mikuláš je tu! Získaj 90 % extra kreditov ZADARMO s promo kódom CERTIK90 pri nákupe od 1 199 kreditov. Len do nedele 7. 12. 2025! Zisti viac:
NOVINKA: Najžiadanejšie rekvalifikačné kurzy teraz s 50% zľavou + kurz AI ZADARMO. Nečakaj, táto ponuka dlho nevydrží! Zisti viac:

Diskusia – 9. diel - Dedičnosť a polymorfizmus

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Posledné komentáre sú na spodnej časti poslednej stránky.
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í.

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

Odpovedať
Čí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

Avatar
Jan Ráž
Člen
Avatar
Odpovedá na slezak-petr
Jan Ráž:2. februára 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

Avatar
Jan Ráž
Člen
Avatar
Jan Ráž:2. februára 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

Avatar
slezak-petr
Člen
Avatar
Odpovedá na Jan Ráž
slezak-petr:7. februára 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?

Odpovedať
Čí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
Odpovedá na slezak-petr
Jan Ráž:7. februára 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ě.

Posledné komentáre sú na spodnej časti poslednej stránky.
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zobrazené 7 správy z 47.