[C#/.NET] OOP Property inheritence probleem

Pagina: 1
Acties:
  • 357 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik probeer onze applicatie een beetje netjes op te zetten qua OOP e.d. maar ik kom er niet helemaal uit met de properties overerving..... neem de teste code hieronder:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections.Generic;
using System.Text;

namespace TestApplication
{
    interface IShape
    {
        String Color
        { get; set; }
        String Form
        { get; set; }
        String GetForm();

    }
    
    class Shape : IShape
    {
        private String _color = "Red";
        public String Color
        {   get { return _color; }
            set { _color = value; }
        }

        private String _form = "Shape";
        public String Form
        {   get { return _form; }
            set { _form = value; }
        }

        public virtual String GetForm()
        { return Form; }
    }

    class Rectangle : Shape
    {
        public new String Color = "Green";
        public new String Form = "Rectangle";
        public override String GetForm()
        { return Form; }
    }

    class Circle : Shape
    {
        public new String Form = "Circle";
        public override String GetForm()
        { return Form; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Shape shape;
            
            if(new Random().Next(1,20) <= 10)
                shape = new Rectangle();
            else
                shape = new Circle();

            Console.WriteLine("shape.GetType()\t\t: " + shape.GetType().ToString());
            Console.WriteLine();
            Console.WriteLine("shape.Color\t\t: " + shape.Color);
            Console.WriteLine("shape.Form\t\t: " + shape.Form);
            Console.WriteLine("shape.GetForm()\t\t: " + shape.GetForm());
            Console.WriteLine();

            if (shape is Circle)
            {
                Circle circle = shape as Circle;
                Console.WriteLine("circle.Color\t\t: " + circle.Color);
                Console.WriteLine("circle.Form\t\t: " + circle.Form);
                Console.WriteLine("circle.GetForm()\t: " + circle.GetForm());
            }
            else
            {
                Rectangle rectangle = shape as Rectangle;
                Console.WriteLine("rectangle.Color\t\t: " + rectangle.Color);
                Console.WriteLine("rectangle.Form\t\t: " + rectangle.Form);
                Console.WriteLine("rectangle.GetForm()\t: " + rectangle.GetForm());
            }

            Console.WriteLine();

            //Whatever shape it is, change its color.........
            shape.Color = "new color!";
            Console.WriteLine("shape.Color\t\t: " + shape.Color);
            if (shape is Circle)
                Console.WriteLine("circle.Color\t\t: " + ((Circle)shape).Color);
            else
                Console.WriteLine("rectangle.Color\t\t: " + ((Rectangle)shape).Color);

            Console.ReadKey();
            
            /* MOGELIJKE UITKOMST 1
            shape.GetType()         : TestApplication.Rectangle

            shape.Color             : Red
            shape.Form              : Shape
            shape.GetForm()         : Rectangle

            rectangle.Color         : Green
            rectangle.Form          : Rectangle
            rectangle.GetForm()     : Rectangle

            shape.Color             : new color!
            rectangle.Color         : Green
            */

            /* MOGELIJKE UITKOMST 2
            shape.GetType()         : TestApplication.Circle

            shape.Color             : Red
            shape.Form              : Shape
            shape.GetForm()         : Circle

            circle.Color            : Red
            circle.Form             : Circle
            circle.GetForm()        : Circle

            shape.Color             : new color!
            circle.Color            : new color!
             */
        }
    }
}


Nu heb ik bijvoorbeeld een class die een bestandsformaat omzet naar een document. Deze maakt dus vele verschillende shapes aan welke allemaal een kleur hebben, dus wil je zoals in regel 86 een generieke manier hebben om de kleur te zetten, net als vele andere properties en dergelijke die voor alle shapes gelijk zijn kunnen zijn, maar een andere implementatie hebben.

Hoe maak je deze OOP structuur nu goed? Want zoals je ziet, werkt deze implementatie niet lekker... De rectangle krijgt niet de niewe kleur, maar houdt zijn eigen kleur.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 12-09 23:07
Zowiezo duid het feit dat je in je inherited classes het keyword 'new' erop dat je niet een al te best ontwerp hebt.
Daarnaast vraag ik me ook af wat de toegevoegde waarde is van die GetForm method. Je hebt toch al een property Form ?

Waarom doe je het niet zo (ff die interface eruit laten, om de boel wat kort te houden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Shape
{
    protected string form;
    protected string color;

    protected abstract void SetProperties();

    public string Form { get { return form; } set { form = value; } }
    public string Color { get { return color; } set { color = value; } }
}

public class Rectangle : Shape;
{
   protected override void SetProperties
   {
      form = "Rect"; 
      color = "Blue";
   }
}


Zowiezo heb je in dit voorbeeld eigenlijk geen polymorphisme nodig; het kan perfect zonder opgelost worden, als je iedere keer de properties in de constructor zet.
Echter, ik heb hier voor die abstracte method gekozen, zodanig dat er geen instances van Shape kunnen gemaakt worden, en, dat je de gebruiker dwingt om die SetProperties method te overriden.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
whoami schreef op vrijdag 25 mei 2007 @ 19:41:
Zowiezo duid het feit dat je in je inherited classes het keyword 'new' erop dat je niet een al te best ontwerp hebt.
Daarnaast vraag ik me ook af wat de toegevoegde waarde is van die GetForm method. Je hebt toch al een property Form ?
De reden is eigenlijk omdat ik overerf van een .Net class. Een usercontrol in dit geval. Deze class heeft zelf al een property bijvoorbeeld met de naam 'Background' waarvan ik een eigen implementatie wil realiseren.
De GetForm echter is puur ter illustratie, dat deze wél goed werkt, maar dat deze me niet genoeg mogelijkheden bied.
Waarom doe je het niet zo (ff die interface eruit laten, om de boel wat kort te houden:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Shape
{
    protected string form;
    protected string color;

    protected abstract void SetProperties();

    public string Form { get { return form; } set { form = value; } }
    public string Color { get { return color; } set { color = value; } }
}

public class Rectangle : Shape;
{
   protected override void SetProperties
   {
      form = "Rect"; 
      color = "Blue";
   }
}


Zowiezo heb je in dit voorbeeld eigenlijk geen polymorphisme nodig; het kan perfect zonder opgelost worden, als je iedere keer de properties in de constructor zet.
Echter, ik heb hier voor die abstracte method gekozen, zodanig dat er geen instances van Shape kunnen gemaakt worden, en, dat je de gebruiker dwingt om die SetProperties method te overriden.
Prima oplossing, en als ik het op deze manier kan doen (of zodra het kwartje valt :P ) zou ik iets gelijks hebben ontworpen, maar je raad het al: gaat niet geheel werken voor mij.
Het probleem blijft namelijk bestaan zodra ik via een algemene shape wil gebruiken voor het zetten van een willekeurige shape (houd er rekening mee dat dit er véél meer kunnen zijn dan een rectangle en een circle in een realitische app). Dit omdat bijvoorbeeld de Background al een public is bij het overerven zelf, én omdat de derived class eigenlijk de implementatie moet verzorgen. Eigenlijk zou dit dus het liefst een virtual zijn in plaats van een public.

Eigenlijk zou ik een vorm van encapsulation willen. Maar dit is dan weer niet geheel mogelijk omdat ik dan niet bij protected, internal, etc eigenschappen kan.....

Wat ik buiten deze psuedo applicatie eigenlijk wil bereiken is applicatie die een document met properties heeft, daarin stijlen, kleuren e.d. en een aantal pagina's. Op die pagina's moeten paginaItems komen. Deze paginaItems wil ik allemaal van dezelfde classe laten erven, en momenteel probeer ik dat van usercontrol. Daarin wil bijvoorbeeld shapes maken, maar ook textblokken en andere paginaitems.
Nu gaat het dus niet helemaal lekker bij de paginaItems base class... deze probeer ik nu goed te krijgen... Misschien dat deze korte beschrijving van het achterliggende probleem wat meer duidelijkheid schept.

[offtopic] whoami, just wondering, is je naam opzettelijk niet in Pascal case? ;) [/offtopic]

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 12-09 23:07
Dus, als ik het goed begrijp wil je overerven van een reeds bestaande .NET class (welke?)
Is het echt nodig dat je acces hebt aan private / protected members ? Anders zou ik kiezen voor encapsulation (adapter pattern). - desnoods kan je nog mbhv reflection die private / protected members aanspreken).

offtopic:
Ja, die naam is express lowercase

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
whoami schreef op vrijdag 25 mei 2007 @ 21:02:
Dus, als ik het goed begrijp wil je overerven van een reeds bestaande .NET class (welke?)
Het UserControl object. Ik ben er sinds ik voor dit object gekozen heb trouwens nog steeds niet van overtuigd dat dit de juiste class is, waarom bv niet Control zelf. Maar het werkt tot nu toe perfect m.u.v. de properties. En het usercontrol heeft veel out of the box ondersteuning die ik wel gebruik
Is het echt nodig dat je acces hebt aan private / protected members ? Anders zou ik kiezen voor encapsulation (adapter pattern). - desnoods kan je nog mbhv reflection die private / protected members aanspreken).
hoe sta je tegenover reflection dan? is dit voor een encapsulated pattern gewenst? of duid dit (normaal gesproken) ook op een kink in het ontwerp?