NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: C# "Vytvoření instance sama sebe" - Předání hodnoty jinému objektu.

V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Jan Kotěhulka:12.2.2017 23:53

Zdravím,
vyskytl se mi tu menší problém ohledně OOP v C#.

Nejlépe to vysvětlím na příkladu:
Dejme tomu, že je vytvořen jeden objekt (instance). Ta obsahuje mnoho hodnot a metod. K provozu této instance z dané třídy potřebuji zavolat metodu nacházející se v třídě druhé - proto zde vytvořím instanci a zavolám příslušnou metodu. Ovšem zde, v druhé třídě potřebuji pracovat s určitými hodnotami z třídy (objektu) první, ale všechny hodnoty jsou uložené v daném objektu a já nemám k nim přístup.
Jediné co mi teď napadá je poslat hodnoty jako parametr, ale zdá se mi že existuje i lepší způsob.

(Přesněji se potřebuji dostat k určitým vlastnostem patřící té třídě)

Přemýšlel jsem, že aby ta druhá třída mohla pracovat již s těmi hodnotami v daném objektu, tak by mohla poslat do ní parametr instance sama sebe :D. Ale o to jsem ještě nikdy neslyšel, třeba budu průkopník.

(Pravděpodobně je to horší na vysvětlení, možná na pochopení)

Zkusil jsem vytvořit obrázek, který vám stejne asi nic neřekne:
Obrázek

Děkuji za odpověď :-)

 
Odpovědět
12.2.2017 23:53
Avatar
Odpovídá na Jan Kotěhulka
Michal Štěpánek:13.2.2017 7:13

Abych pravdu řekl, dost dobře nechápu, čeho chceš dosáhnout, ale nemohl bys nějakou třídu od jiné třeba podědit?

Nahoru Odpovědět
13.2.2017 7:13
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Jan Kotěhulka
Neaktivní uživatel:13.2.2017 8:30

Jestli metoda potřebuje pracovat s nějakým objektem, tak jí prostě předáš ten objekt:

class First
{
        //spousty vlastností a metod
}

class Second
{
        public void Metoda(First instance)
        {
                //nyní pracuj s instancí 1. třídy
        }
}
Editováno 13.2.2017 8:30
Nahoru Odpovědět
13.2.2017 8:30
Neaktivní uživatelský účet
Avatar
Lako
Člen
Avatar
Lako:13.2.2017 10:17

Jestli to dobře chápu, tak se navázájem třídy mohou požívat takto:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
  public static void Main()
  {
    Console.WriteLine("Hello C#");
        Trida1 trida1 = new Trida1();
    Trida2 trida2 = new Trida2();
    trida1.Trida2 = trida2;
    trida2.Trida1 = trida1;
  }
}

public class Trida1
{
   public Trida2 Trida2 { get; set; }

  public void NejakaMetoda()
  {
    Trida2.PrvniMetoda();
  }

  public void DalsiMetoda()
  {}

}

public class Trida2
{
  public Trida1 Trida1 { get; set; }

  public void PrvniMetoda()
  {

  }

  public void DruhaMetoda()
  {
    Trida1.DalsiMetoda();
  }


}

(online: http://volatileread.com/…ppetcompiler?…)
Není to ale uplně dobré.
Spíš by chtělo vědět k čemu to potřebuješ a možná zvolit lepší návrh...

 
Nahoru Odpovědět
13.2.2017 10:17
Avatar
Jan Kotěhulka:13.2.2017 16:25

Pardon, asi jsem to špatně vyjádřil...

using System;

class Program
{
  static void Main()
  {
    Game game = new Game();
    game.MainLoop();
  }
}

class Game
{
   public int zivot { get; private set; }
   public int skore { get; private set; }

  public void MainLoop()
  {
    GameFrame gameframe = new GameFrame();

    for(;;)
        {
          // Prubeh hry
          gameframe.vykresli();
        }
   }
}


class GameFrame
{
   public void vykresli()
   {
      // Zde nejaky "graficky" prvek
      Console.Write("Zde potrebuji vypsat skore"); // Zde potrebuji vlastnost, ktera se ale nachazi ve tride Game
      // Je zde moznost vyuzit parametru, ale co kdyz tech vlastnosti bude vic a budou vice sofistikovane
   }
}

Děkuji všem za rady.
Zkoušel jsem tu dědičnost, ale ta dědí pouze dané metody ale ne hodnoty, nebo se mýlím?

 
Nahoru Odpovědět
13.2.2017 16:25
Avatar
Erik Šťastný:13.2.2017 16:28

Určitě i hodnoty když v ní jsou v definici třídy, nicméně ty za běhu samozřejmě ne, dědí se třída, ne její instance.

Každopádně dělá se to parametrem přesně jak říkáš v komentu když jich máš 50 těch parametrů, můžeš jako parametr předat rovnou celou instanci v které je těch 50 proměnných které potřebuješ.

Editováno 13.2.2017 16:28
 
Nahoru Odpovědět
13.2.2017 16:28
Avatar
Jan Kotěhulka:13.2.2017 16:37

Tak jsem to s tou dědičností myslel :)

A jak v tomto případě mám předat tu instanci, když už jsem uvnitř té třídy "Game"?

 
Nahoru Odpovědět
13.2.2017 16:37
Avatar
Martin Gabriel
Tvůrce
Avatar
Odpovídá na Jan Kotěhulka
Martin Gabriel:13.2.2017 16:55

Takhle:

class Game
{
    public int zivot { get; private set; }
    public int skore { get; private set; }

    public void MainLoop()
    {
        GameFrame gameframe = new GameFrame(this);

        for (;;)
        {
            // Prubeh hry
            gameframe.vykresli();
        }
    }
}


class GameFrame
{
    private Game game;

    public GameFrame(Game g)
    {
        this.game = g;
    }

    public void vykresli()
    {
        // Zde nejaky "graficky" prvek
        Console.Write("Score: " + game.skore); // Zde potrebuji vlastnost, ktera se ale nachazi ve tride Game
                                               // Je zde moznost vyuzit parametru, ale co kdyz tech vlastnosti bude vic a budou vice sofistikovane
    }
}
Editováno 13.2.2017 16:57
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
13.2.2017 16:55
"Be the change you want to see in the world" - Michael Scofield
Avatar
Odpovídá na Martin Gabriel
Jan Kotěhulka:13.2.2017 17:10

Martine perfektní :)

Než ti to odkliknu, mohl by jsi mi lehce objasnit, jak to funguje

GameFrame gameframe = new GameFrame(this);

Spis, jak to, že parametr this bere tu instanci. Díky

A to, že se nedá tato instance vytvořit v rámci celé dané třídy, ale jen v nějaké metodě je asi zapříčiněné tím, že v té době nějak neexistuje nebo proč?

Ptám se proto, že bych se rád poučil z chyb a věděl proč to tak funguje :)

Díky

 
Nahoru Odpovědět
13.2.2017 17:10
Avatar
Martin Gabriel
Tvůrce
Avatar
Odpovídá na Jan Kotěhulka
Martin Gabriel:13.2.2017 17:55

Pod klíčovým slovem this se skrývá instance dané třídy. Takže do konstruktoru třídy GameFrame předáme parametrem instanci třídy Game. Mohl bys předávat instanci té třídy i přímo do metody vykresli(), ale to bys ji předával při každém vykreslení, což je zbytečné.

Jinak druhému dotazu moc nerozumím. Ale v zásadě v Mainu jsi vytvořil instanci třídy Game a zavolal metodu MainLoop(). V této chvíli instance třídy Game existuje a je uložená někde v paměti. Dá se k ní přistupovat přes veřejné metody a proměnné.

GameFrame gameframe = new GameFrame(this);

Tímhle řádkem jsi řekl, že se má vytvořit nová instance třídy GameFrame a zavolal jsi její konstruktor. V konstruktoru jsi jí pomocí this předal instanci třídy Game (protože jsi ji vytvořil v třídě Game), takže teď k ní můžeš přes veřejné metody a proměnné přistupovat.

Kdyžtak doporučuju projít zdejší tutoriály o OOP, jsou dost kvalitní a zodpoví to mnoho otázek. :)
Užitečný odkaz o klíčovém slovu this : https://msdn.microsoft.com/…k1507sz.aspx?…

Klidně se na cokoli dalšího ptej. :)

Editováno 13.2.2017 17:56
Nahoru Odpovědět
13.2.2017 17:55
"Be the change you want to see in the world" - Michael Scofield
Avatar
Jan Kotěhulka:13.2.2017 18:01

Díval jsem se zrovna co všechno this umí a jsem překvapen :D. Jinak zdejší tutoriály na OOP jsem projížděl, ale měl bych si je zopakovat :). Ono to člověku je vše jasné, než nezačne sám něco programovat.

Ještě zkusím upřesnit ten poslední dotaz.

class Game
{
    public int zivot { get; private set; }
    public int skore { get; private set; }
    GameFrame gameframe = new GameFrame(this); // Zde je chyba, proc?

    public void MainLoop()
    {
        GameFrame gameframe = new GameFrame(this); // Zde je vse v poradku.

        for (;;)
        {
            // Prubeh hry
            gameframe.vykresli();
        }
    }
}
 
Nahoru Odpovědět
13.2.2017 18:01
Avatar
Martin Gabriel
Tvůrce
Avatar
Odpovídá na Jan Kotěhulka
Martin Gabriel:13.2.2017 18:50

Chyba tam vyskočí proto, že instance se vytvoří poté, co proběhne konstruktor. V tomhle případě instance ještě neexistuje, proto to hlásí chybu. Dobré je to napsat například takhle:

class Game
{
    public int zivot { get; private set; }
    public int skore { get; private set; }
    private GameFrame gameframe;

    public Game()
    {
        gameframe = new GameFrame(this); // v momentě, kdy se vykoná tento kód je jasné, o jakou instanci se jedná
    }

    public void MainLoop()
    {
        while (true) // je zvyk psát nekonečný cyklus takhle, ale samozřejmě to už je otázka vkusu :)
        {
            // Prubeh hry
            gameframe.vykresli();
        }
    }
}
Nahoru Odpovědět
13.2.2017 18:50
"Be the change you want to see in the world" - Michael Scofield
Avatar
Jan Kotěhulka:13.2.2017 19:17

Funguje to. Moc díky za tvůj čas a vysvětlení. Pomohl jsi mi :).

 
Nahoru Odpovědět
13.2.2017 19:17
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 13 zpráv z 13.