Oprettet man. d. 27. august 2012 kl. 09:42:20

munkeholm
munkeholm (12.135 point. Point ude: 30)

hjælp til nedarvning

hey

jeg har et program hvor jeg skal have lavet en masse funktioner men de alle har en masse til fælles.

så min plan var at bruge Block som parent også ellers lave SleepBlock, TimeBlock osv. som ville arve de forskellige ting fra Block.

det går også fint nok ... men når jeg f.eks. gerne vil lave en List<Block> og vil hente f.eks. en sleepblock ud. er den selvfølgelig en Block og jeg kan derfor ikke tilgå sleep's metoder og parametre ..

Hvor er det jeg misser noget i f.eks.? /

List<Block> list = new List<Block>();
list.add(sleepBlock);

foreach (Block b in list)
{
// HER vil jeg gerne gøre en masse forskelligt ved de her objekter .. altså sleepBlock/TimeBlock osv. som kan være rigtig mange forskellige.

}

Skrevet man. d. 27. august 2012 kl. 09:47:27| #1

runesoft
runesoft (28.541 point)
Du bliver nødt til at teste på typen og caste til den type du skal bruge.

if(b is SleepBlock){
  ((SleepBlock)b).sleep();
}

Skrevet man. d. 27. august 2012 kl. 09:51:33| #2

munkeholm
munkeholm (12.135 point)
netop det jeg gerne ville undgå da check og typecast på 100 forskellige objekter kunne ende ud i en utrolig lang metode af hvad jeg lige kan forudse. eller er det bare mig ?

if(b is SleepBlock){
// 1
}else if(b is TimeBlock)
{

}else if()

osv. osv.

der er intet galt i at gøre det på den måde ?

Skrevet man. d. 27. august 2012 kl. 10:01:12| #3

bvli
bvli (23.460 point)
Hej.

Det er nemlig en 'sjov' problemstilling. Du er nødt til at vide noget om co- og contra-variance.

Check evt. denne informative artikel: http://tomasp.net/ (...)

Skrevet man. d. 27. august 2012 kl. 10:13:58| #4

mireigi
mireigi (20.147 point)
En måde at gøre det på er at loope over hver type i din liste.

Det er i princippet det samme som en masse check, men jeg syntes det er mere overskueligt på den måde.

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

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Vehicle> vehicles = new List<Vehicle>();
            vehicles.Add(new Car());
            vehicles.Add(new Car());
            vehicles.Add(new Car());
            vehicles.Add(new MotorCycle());
            vehicles.Add(new MotorCycle());
            vehicles.Add(new MotorCycle());

            Console.WriteLine(vehicles.Sum(f => f.Wheels));
            Console.ReadLine();
            foreach (Car item in vehicles.FindAll(f => f.GetType() == typeof(Car)))
            {
                item.RemoveLeftBackTire();
                item.RemoveRightBackTire();
            }

            foreach (MotorCycle item in vehicles.FindAll(f => f.GetType() == typeof(MotorCycle)))
            {
                item.RemoveBackTire();
            }

            Console.WriteLine(vehicles.Sum(f => f.Wheels));
            Console.ReadLine();
        }
    }

    class Vehicle
    {
        public int Wheels { get; set; }
    }

    class Car : Vehicle
    {
        public Car()
        {
            base.Wheels = 4;
        }

        public void RemoveLeftBackTire()
        {
            base.Wheels--;
        }

        public void RemoveRightBackTire()
        {
            base.Wheels--;
        }
    }

    class MotorCycle : Vehicle
    {
        public MotorCycle()
        {
            base.Wheels = 2;
        }

        public void RemoveBackTire()
        {
            base.Wheels--;
        }
    }
}

Skrevet man. d. 27. august 2012 kl. 10:31:12| #5

munkeholm
munkeholm (12.135 point)
Du har helt ret i det er mere overskueligt, sidder lige og prøver at læse artiklen som blev linket.

Men der ville ikke være nogen indvendinger mod at bruge en liste af checks for at typecaste på den måde ? altså det vil helt sikkert virke og være rimelig simpelt at kode, men rent kode mæssigt er der intet galt i det ?

For så tror jeg at det bliver min løsning efter alt.

Skrevet man. d. 27. august 2012 kl. 12:39:21| #6

mireigi
mireigi (20.147 point)
Der er ikke noget galt i det nej, men i stedet for en masse if-sætninger, ville jeg nok bruge switch-case i stedet for:

foreach (Vehicle vehicle in vehicles)
{
  switch (vehicle.GetType())
  {
      case typeof(Car):
        ((Car)vehicle).RemoveLeftBackTire();
        break;
      case typeof(MotorCycle):
        ((MotorCycle)vehicle).RemoveBackTire();
        break;
      default:
        break;
  }
}

Skrevet man. d. 27. august 2012 kl. 12:54:13| #7

mireigi
mireigi (20.147 point)
Kiggede lidt rundt, og fandt ud af, at du kan nøjes med én metode, hvis du bruger Reflection:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Vehicle> vehicles = new List<Vehicle>();
            vehicles.Add(new Car());
            vehicles.Add(new Car());
            vehicles.Add(new Car());
            vehicles.Add(new MotorCycle());
            vehicles.Add(new MotorCycle());
            vehicles.Add(new MotorCycle());

            Console.WriteLine(vehicles.Sum(f => f.Wheels));
            Console.ReadLine();

            foreach (Vehicle vehicle in vehicles)
            {
                vehicle.InvokeMethod(typeof(Car), vehicle, "RemoveLeftBackTire", null);
                vehicle.InvokeMethod(typeof(MotorCycle), vehicle, "RemoveBackTire", null);
            }


            Console.WriteLine(vehicles.Sum(f => f.Wheels));
            Console.ReadLine();
        }
    }

    class Vehicle
    {
        public int Wheels { get; set; }

        public void InvokeMethod(Type type, object classInstance, string methodName, object[] parameters)
        {
            if (type != null && classInstance.GetType() == type)
            {
                MethodInfo method = type.GetMethod(methodName);
                if (method != null)
                {
                    object result = null;
                    int parameterCount = method.GetParameters().Length;
                    if (parameterCount == 0)
                    {
                        result = method.Invoke(classInstance, null);
                    }
                    else
                    {
                        result = method.Invoke(classInstance, parameters);
                    }
                }
            }
        }

    }

    class Car : Vehicle
    {
        public Car()
        {
            base.Wheels = 4;
        }

        public void RemoveLeftBackTire()
        {
            base.Wheels--;
        }

        public void RemoveRightBackTire()
        {
            base.Wheels--;
        }
    }

    class MotorCycle : Vehicle
    {
        public MotorCycle()
        {
            base.Wheels = 2;
        }

        public void RemoveBackTire()
        {
            base.Wheels--;
        }
    }
}

Skrevet man. d. 27. august 2012 kl. 13:11:39| #8

runesoft
runesoft (28.541 point)
Nu ved jeg jo ikke helt hvad der er du vil. Du kunne gøre det at du laver en abstrakt metode på Block, og implementerer den på dine subklasser. Så ville du ikke skulle caste dine objekter før du kalder dem.

Skrevet man. d. 27. august 2012 kl. 13:21:19| #9

mireigi
mireigi (20.147 point)
@runesoft (#8): Det er vel kun holdbart så længe det giver mening at metoden hedder/gør det samme? Vil nødig være den der skal vedligeholde et system, hvor hver klasse har X antal metoder med samme navn, men hver metode gør noget forskelligt.

Skrevet tir. d. 28. august 2012 kl. 00:54:59| #10

arne_v
arne_v (1.048.788 point)
Jeg er enig med #8.

Hvis ikke det giver mening at have en abstrakt metode alle overrider, saa giver det heller ikke mening at have en List<basistype> og ville goere noget paa alle elementer.

Hvis man mangler et godt metode navn, saa er Execute brugt en del til den slags.

Skrevet tir. d. 28. august 2012 kl. 09:58:32| #11

munkeholm
munkeholm (12.135 point)
grunden til jeg har valgt at have en basictype er fordi så kan parameter hentes uden at kende den specifike type

f.eks. indeholder alle elementer noget perlcode som dog er forskelligt og her slipper jeg så for tjekket efter typen af element.


hele problemet ligger som sagt i at jeg har en liste af block objekter som jeg vil tilføje til et listview/listbox og her har jeg brug for specifike parameter som kun nogle af mine elementer har.


men i har helt ret, der er nogle metoder som kunne være smarte at lave abtrakte i block og udfylde.

Skrevet tir. d. 28. august 2012 kl. 22:45:31| #12

janus_007
janus_007 (34.085 point)
munkeholm, du skal bare lave en type scanner eller bruge et fornuftigt Dependency Injection framework, så kan du hente typen ud på navnet og behøver ikke det prut med switch/ case eller andet for-each-guf :)

Skrevet ons. d. 29. august 2012 kl. 01:52:20| #13

mireigi
mireigi (20.147 point)
Vil lige henlede opmærksomheden til mit indlæg i #7. Det kan gøre, hvad du har behov for, uden at du behøver ændre på eksisterende nedarvede klasser. Det er kun på basis-klassen at metoden skal ligge.

Skriv et indlæg




Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] [img]link til billede[/img]
Web- og emailadresser omdannes automatisk til links

Log ind

   


Seneste spørgsmål

Mine float værdier mister '.' når jeg læser tal i dem

Oprettet den 23. maj 2013 kl. 22.56
CodingJoe giver 30 point for svar | Giv et svar »

Redigere appconfig settings fra web.config i runtime

Oprettet den 22. maj 2013 kl. 14.41
lasserasch giver 60 point for svar | Giv et svar »

Extension methods med constraint på interface

Oprettet den 18. maj 2013 kl. 19.26
CodingJoe giver 30 point for svar | Giv et svar »








Tips & Tricks fra PC World

Teaser billede

Fem smarte funktioner i din Mac som du sikkert ikke kender

Her har du fem muligheder for at tweake din Mac på en fed måde.


Anmeldelser fra PC World

Teaser billede

Test: Samsung Galaxy S4 er et hit - trods gøglertricks

Kan Samsung beholde førertrøjen i det store Android-race? Galaxy S4 er smækfyldt med innovative funktioner, men også med en del gøgl. Er det for meget? Få vores dom over Samsungs nye topmodel.


Seneste blogindlæg

Teaser billede

Tvangslukke spørgsmål: Hvad er den bedste løsning?

Hej Vi har mange åbne spørgsmål på Eksperten. Vi ville gerne tvangslukke dem - så et spørgsmål efter f.eks. 6 måneder lukkes. Men der er et par uklarheder som ville være gode at få lidt input til:...


Nyheder fra PC World

Teaser billede

Ny opfindelse: Oplad din mobil på 20 sekunder

Måske er det snart slut med at lade mobilen op hver aften. Med ny opfindelse kan telefonen få fuld energi på sølle 20 sekunder.


Nyheder fra Computerworld

Teaser billede

Galleri: De 10 vildeste datacentre i verden

I en gammel kirke, i et oppusteligt telt, på nedlagte militæranlæg eller midt i ørkenen. Der er ingen grænser for, hvor man kan banke et datacenter op. Her er de 10 sejeste anlæg i verden. I...


IT Kurser
Samarbejdspartnere

Udgiver · © 2013 IDG Danmark A/S · Hørkær 18 · 2730 Herlev · Tlf.: 77 300 300 · Fax: 77 300 301 · Brug af personoplysninger