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# - problém s interface (jak zjistit skrz který interface je instance tvořena)

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

Aktivity
Avatar
petrekov
Člen
Avatar
petrekov:7.2.2017 17:47

Zrovna jsem dočetl v OOP přetypování a hiearchii objektů, snad jsem to tedy nepřehlédl, mám totiž ohledně toho takový problém. Mám třídu Postava z které vytvářím instance skrze tři různé interface (IBojovnik, IMag, ILukostrelec). Problém je, že nijak nedokážu zjistit pomocí kterého z těch interface byla instance vytvořena. Pokud se zeptám pomocí (moje_instance is IBojovnik) tak je to vždy pravda, protože ji hádám třída obsahuje, i když přes ni nebyla vytvořena, snad to chápu dobře... Vím, že by to šlo skrze dědičnost vyřešit, ale chtěl jsem to zkusit rozlišovat, těmi interface. Takže dá se nějak zjistim pomocí které interface byla instance vytvořena? Pokud budu mít například :

IBojovnik hrac = new Postava();

Tak abych se mohl zeptat podmínkou, zda byl hrac vytvořen skrze IBojovnik či nikoliv.
Za připadnou pomoc děkuju a snad jsem to napsal správně a srozumitelně :D

Odpovědět
7.2.2017 17:47
Do diskuze musí jít člověk připraven ztratit svůj názor
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na petrekov
Jan Vargovský:7.2.2017 18:01

Moc ti nerozumím tbh. Nevytváříš instanci interfacu (nikdy - co by se asi zavolalo, když bys na to poslal nějakou zprávu?)

Ukaž tu hierarchii těch tříd.

 
Nahoru Odpovědět
7.2.2017 18:01
Avatar
petrekov
Člen
Avatar
petrekov:7.2.2017 18:24
static void Main(string[] args)
        {
            IBojovnik hrac = new Postava();
            ILukostrelec hrac2 = new Postava();
            IMag hrac3 = new Postava();
        }

->zde si vytvořím tři instance ze stejné třídy, ale skrze jiný interface pokaždé a mě jde o to, abych zjistil skrze jaký interface jsou vytvořeny. Třeba to nejde, proto se ptám.

Kupříkladu bude třída postava obsahovat hromadu metod pro všechny tři typy hrdinů(bojovník,lu­čišník,mág), ale některé se budou lišit a v těch se budu například chtít zeptat (Je hrac2 bojovník?) tedy, že byl vytvořen skrze interface IBojovnik
takto->

IBojovnik hrac2 = new Postava();

pokud by byl vytvořen jinak, tak by to nesplnilo podmínku, kdyby byl například stvořen takhle
->

IMag hrac2 = new Postava();

Omlouvám se, jestli to píšu nesrozumitelně :/

Nahoru Odpovědět
7.2.2017 18:24
Do diskuze musí jít člověk připraven ztratit svůj názor
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na petrekov
Jan Vargovský:7.2.2017 19:34

Můžeš ukázat ty 3 interfacy? Nevím jestli se snažíš o explicitní implementaci interfacu nebo máš prostě jen různé metody u každého typu.

Každopádně:

IBojovnik hrac = new Postava();
ILukostrelec hrac2 = new Postava();
IMag hrac3 = new Postava();

Tyhle 3 řádky ti vytvoří úplně tu samou instanci. To do jakého typu si jí uložíš pak jen určuje jaké typy zpráv tomu objektu můžeš poslat.

Pošli ty interfacy a kdyžtak tu třídu Postava (stačí jen signatury + z čeho to dědí a co to implementuje).

Jo a btw, dávej odpovědět, jinak si toho třeba ani nevšimnu...

Editováno 7.2.2017 19:35
 
Nahoru Odpovědět
7.2.2017 19:34
Avatar
Petr Nymsa
Tvůrce
Avatar
Odpovídá na petrekov
Petr Nymsa:7.2.2017 19:50

Snad chápu dobře, že ti jde o vytvoření různých "tříd" hrdinů. Způsobem jakým to, ale vytváříš, mi přijde, že jsi zřejmě špatně pochopil jak to funguje.

Dost pravděpodobně máš napsaného něco takového

Postava : IBojovnik, IMag, ILukostrelec

Tímhle jsi řekl, že objekt Postava implementuje tyto 3 rozhraní, jinými slovy disponuje "schopnostmi" všech třech typů hrdinů.

Pokud vytvoříš instanci skrz rozhraní

IBojovnik hrac = new Postava();

Tímto jsi vytvořil instanci třídy Postava, kteá umí vše, co jsi do ní implementoval. Každopádně na tuto instanci "se díváš skrze" rozhraní IBojovnik - tedy, lze volat pouze metody, které umí IBojovnik. To, ale neznamená, že tato postava , neumí i další schopnosti - lukostřelba, magie.

Jedna z možných správných řešení.

  • Vytvoř nějakou bázovou třídu "Postava", která bude mít základní společné rysy pro všechny druhy hrdinů
  • Od ní podědíš a vytvoříš již specializované druhy - Bojovník, Mág,...
  • Potom s tím můžeš pracovat skrz obecnou třídu, ale doptávat se jakého skutečného typu je.

Příklad (pouze nástřel, ne funkční řešení)

class Postava  {  int zivoty; virtual void Bojuj() }
class Bojovnik : Postava
 { override void Bojuj() { // specialni zpusob boje bojovnika }

Postava hrac = new Bojovnik(); ... if(hrac is Bojovnik) ... // vis ze je bojovnik

Druhá možnost, je definovat různá rozhraní IBojovnik ILukostrelba.
A implementovat třeba charakter Lovec

class Lovec : IBojovnik, ILukostrelba

Třída Lovec je druh postavy, která je bojovníkem, ale umí i střílet z luku.
Za to takový gladiátor

class Gladiator : IBojovnik

Je druh, který umí dobře bojovat, ale neumí ovládat lukostřelbu.
Samozřejmě toto ber jako ilustraci, každopádně takto si myslím, že by měla být tvoje správná cesta. Pokud jsem tě špatně pochopil oprav mě. Pokud máš otázky, ptej se :)

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
7.2.2017 19:50
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
petrekov
Člen
Avatar
Odpovídá na Petr Nymsa
petrekov:7.2.2017 21:42

Jo přes dědičnost mě to napadlo původně, pak jsem se dostal k rozhraním a začal tyhle podivné cesty/experimenty. Já jsem si to spletl, že to prostě je jakási forma, která vybere z třídy to potřebné a využije, ale jak si řekl, že se přes to jen dívá, tak mi to došlo. Trochu blbě jsem to pochopil... :). A ano odhadl si co jsem myslel, moc díky za pomoc :) už na tom dělám s třídama a opět jsem na mrtvém bodě :D. Takže pokud je jen nějaká drobná chybička, byl bych opravdu rád za ještě jednu radu, v případě že je to těžší a nebo je to až někde dál v tutorialu, tak nic, já se k tomu prokoušu :).

Mám statickou třídu Mechanismy, ve které bude funkce na výběr classy (Bojovní, lukostřelec, mág)

static public void Vytvoreni_Postavy(out Postava hrac_out)
        {
            Console.WriteLine("Vítej ve hře Fantsy Wordl");
            Console.WriteLine("<stiskni libovoulnou klávesu pro pokračování>");
            Console.ReadKey();
            Console.Clear();
            Console.WriteLine("Vyber si povolání pomocí čísel-> \n [1] - Bojovník \n [2] Lukostřelec \n [3] Mág \n ___________________ \n ->");
            string volba = Console.ReadLine();
            switch (volba)
            {
                case "1":
                    {
                        Bojovnik hrac = new Bojovnik();
                    }
                    break;
                case "2":
                    {
                        Lukostrelec hrac = new Lukostrelec();
                    }
                    break;
                case "3":
                    {
                        Mag hrac = new Mag();
                    }
                    break;
            }
            hrac_out = hrac;
        }
  • jak sis jistě všiml je tam zásadní chyba. :D Pomocí out si chci do hlavního vlákna nahodit vytvořenou postavu. Už jsem to v jedné hře pro trénování dělal, ale tam nebyly classy. Ošetření vstupů jsem neřešil, chápu že takhle to hned spadne, teď řeším jen ty classy.
static void Main(string[] args)
        {
            Postava hrac;
            Mechanismy.Vytvoreni_Postavy(hrac);
        }
  • problém je, že Postava je třída abstraktní z které dědím ty classy (bojovnik,lukos­trelec,mag), jenže pokud ve třídě mechanismy, provedu hráče vytvořením postavy, jak odtud dostanu tu postavu ven? V případě, kdy byl hrac pokaždé instancí jedné a té samé třídy, tak jsem jí z toho dostal ven, tak jak to mám v příkladu (vytvářel jsem instanci třídy Postava), jenže jak mám programu říct, jaká třída bude ta, kterou budu chtít dostat ven?

Jestli je to složitý k vysvětlení, někde to tu je nebo to popisuju blbě, tak to nech být :D ať moc neotravuju.

Nahoru Odpovědět
7.2.2017 21:42
Do diskuze musí jít člověk připraven ztratit svůj názor
Avatar
petrekov
Člen
Avatar
Odpovídá na Petr Nymsa
petrekov:7.2.2017 21:58

Ahh sorry jsem pitomec... Stačí nahradit Bojovnik za Postava a napravo od = to nechat stejné při vytváření instance.

case "1":
                    {
                        Postava hrac = new Bojovnik();
                        hrac_out = hrac;
                    }
                    break;
  • příště víc uvažování a zkoušení, než obtěžování :)
Nahoru Odpovědět
7.2.2017 21:58
Do diskuze musí jít člověk připraven ztratit svůj názor
Avatar
Petr Nymsa
Tvůrce
Avatar
Odpovídá na petrekov
Petr Nymsa:7.2.2017 22:17

Nepoužívej v tomhle případě out parametr, ale metoda Vytvoreni_postavy by mela vratit instanci tridy Postava

Nahoru Odpovědět
7.2.2017 22:17
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
vajkuba1234
Člen
Avatar
Odpovídá na petrekov
vajkuba1234:7.2.2017 23:28

Ano, jak psal Petr. Koukni treba na Factory method pattern. Tento vzor slouzi prave pro vytvareni instanci. :)

Nahoru Odpovědět
7.2.2017 23:28
No hope, no future, JUST WAR!
Avatar
petrekov
Člen
Avatar
Odpovídá na Petr Nymsa
petrekov:8.2.2017 19:47

Ahh to mě vůbec nenapadlo, moc díky, jde se na to :D.

Nahoru Odpovědět
8.2.2017 19:47
Do diskuze musí jít člověk připraven ztratit svůj názor
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 10 zpráv z 10.