Autor Beitrag
Holger_S
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 19.09.12 21:33 
Hallo liebe Community,


vermutlich ist mein Problem sehr trivial und einige hauen sich beim Lesen mit der Hand vor den Kopf aber ich stecke hier ein wenig fest.

Folgende Situation gibt sich mir grade:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Public class Race {

  private Attribute[] attributeList;
  private Bonus[] bonusList;

public Attribute[] AttributeList { get { return attributeList; } set { this.attributeList = value; } }
public Bonus[] BonusList { get { return bonusList; } set { this.bonusList = value; } }

...
}


ist meine allgemeine Klasse.
Es gibt natürlich auch eine konkrete Rasse, diese schaut wiefolgt aus


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
 public class Human : Race
    {
       public Attribute[] attributeArray = new Attribute[7];
       public Bonus[] bonusArray = new Bonus[1];

 public human () 
    {
            SetAttributeList(); // hier werden nur konkrete Elemente in eine Liste gespeichert
            SetBonusList(); // das Gleiche 
            this.AttributeList = attributeArray; //hier wollte ich die "Variablen" an Race übergeben ?!
            this.BonusList = bonusArray;

    }


Während des Programms kann man eine konkrete Rasse wählen und diese soll sich dann initialisieren.
Ziel von mir ist es gewesen an die Klasse Race die Werte die in Human erzeugt werden weiter zu reichen.


Leider funktioniert das nicht so wie geplant und ich seh glaube ich den Wald vor Bäumen kaum.

Mir ist bewußt das mein Code nicht der schönste ist aber irgendwo fängt man ja mal an.

Falls weitere Codeausschnitte fehlen sollten zum Verständnis, so werde ich die dann natürlich einfügen.

Ich hoffe jemand kann mir einen Tip geben zum weiterkommen.
Derzeit habe ich das Problem das in der Endausgabe die Klasse Race natürlich leer bleibt und keine Einträge erhalten hat in der eigenen Liste.
Ist meine Übergabe falsch ?
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 19.09.12 21:59 
Wie genau meinst du das?

Willst du eine Referenz von Human erstellen und von dort Daten an die Eltern-Klasse Race geben?
Im Konstruktor geht das ganz leicht:
ausblenden C#-Quelltext
1:
public Human() : base(Parameter) { /* ... */ }					

Das fordert aber, dass du ein paar entsprechende Konstruktoren definierst.




Ich sollte genauer lesen. ^^

Du möchtest also von einer erbenden Plasse Daten an die vererbende Klasse geben?
Die erbende Klasse besitzt alle Attribute der Parent-Klasse, die entweder öffentlich (public) oder als geschützt (protected) markiert sind. Mit protected gibst du also an, dass nur die erbenden Klassen dieses Klassen-Attribut besitzen und auch nutzen können.

Du müsstest die beiden Felder also beide mit protected definieren und nicht private.

Allerdings würde ich dan doch lieber die EIgenschaften aufrufen, da du in den Eigenschaften direkt die Kontrolle der übergebenen Daten ab wickeln kannst, dann musst du das nirgendwo anders in der Klasse oder außerhalb erledigen, da das schon automatisch geschieht, wenn du der Eigenschaft einen neuen Wert übergibst.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 19.09.12 22:16 
Merkwürdig das du versuchst attributeArray und bonusArray 2 mal zu definieren? Wieso nicht aus dem Nachfahren direkt die Vorfahren Felder ändern?

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
public class Race 
{
    public Attribute[] AttributeList { get; protected set; }
    public Bonus[] BonusList { get; protected set; }
}

public class Human : Race
{
    public Human()
    {
        this.AttributeList = new Attribute[7];
        this.BonusList = new Bonus[1];
        SetAttributeList();
        SetBonusList();
    }
}


Wobei sich das ganze immer noch merkwürdig anfühlt. Du weißt scheinbar erst im Nachfahren genau wieviele Attribute und Boni du brauchst. Dann denke ich mal haben die eigentlich auch eine konkrete Bedeutungen und Namen. Wieso sind das dann nicht konkrete Properties der Klassen sondern irgendwie in Listen zusammengefasst? Oder anders gefragt wenn jemand die Human Klasse über eine Race Variable verwendet woher soll er wissen wofür zum BEispiel Attribut 4 gut ist?
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 19.09.12 22:30 
Ralf Jansen hat recht.
Definiere doch an Stelle des Arrays ein Dictionary, in dem du als Key immer einen Namen angibst.
Dann kannst du eindeutig auf ein Attribut zugreifen.
Aber verstehen tue ich nicht, warum du das so kompliziert machst.

Was das kapseln der Felder angeht, warum nicht?
Ich sehe darin grundsätzlich kein Problem, weil man dann im set-Teil der Eigenschaft eine neue Referenz direkt überprüfen kann. Ob das hier so sinnvoll ist, sei einmal dahin gestellt.

Was ich dann an deiner Stelle aber tun würde, ist die Arrays gar nicht öffentlich zur Verfügung zu stellen, sondern den Zugriff über Methoden ablaufen zu lassen. Das Hinzu fügen, ausgeben und entfernen einzelner Attribute kann dann noch einmal direkt überprüft werden.
Holger_S Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 19.09.12 22:32 
Gut mittlerweile habe ich das Problem gelöst.
Vermutlich eher schlecht als recht aber um vielleicht etwas mehr Einblick zu geben.

ausblenden volle Höhe C#-Quelltext
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:
 public class Human : Race
    {
           public string raceName = "Mensch";
           public Value_Classes.Attribute[] attributeArray = new Value_Classes.Attribute[7];
           public Value_Classes.Bonus[] bonusArray = new Value_Classes.Bonus[1];
    
        public Human()
        {
           
            SetAttributeList();
            SetBonusList();
            this.AttributeList = attributeArray;
            this.BonusList = bonusArray;
            this.RaceName=raceName;

            
            
        }

        public Strengh str = new Strengh(3310);
        public Consitution con = new Consitution(3310);
        public Dexterity dex = new Dexterity(3310);
        public Perception per = new Perception(3310);
        public Intelligence intel = new Intelligence (3,3,10);
        public Willpower will = new Willpower(3310);
        public Charisma cha = new Charisma(3310);


        public Bonus bonus1 = new Bonus("Schaffensdrang""10 zusätzliche CP's");
        
          


        public void SetBonusList()
        {
            bonusArray[0] = bonus1;
        }
        public void SetAttributeList()
        {

            attributeArray[0] = str;
            attributeArray[1] = con;
            attributeArray[2] = dex;
            attributeArray[3] = per;
            attributeArray[4] = intel;
            attributeArray[5] = will;
            attributeArray[6] = cha;

        }


ist die komplette Klasse "Mensch"
Als vergleich mal ein Zwerg:

ausblenden volle Höhe C#-Quelltext
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:
public class Dwarf : Race
    {
        private string raceName = "Zwerg";
        public Value_Classes.Attribute[] attributeArray = new Value_Classes.Attribute[7];
        public Value_Classes.Bonus[] bonusArray = new Value_Classes.Bonus[4];

        public Strengh str = new Strengh(3310);
        public Consitution con = new Consitution(3312);
        public Dexterity dex = new Dexterity(2210);
        public Perception per = new Perception(229);
        public Intelligence intel = new Intelligence(2210);
        public Willpower will = new Willpower(3310);
        public Charisma cha = new Charisma(2210);

        public Dwarf() 
        {
            SetAttributeList();
            SetBonusList();
            this.AttributeList = attributeArray;
            this.BonusList = bonusArray;
            this.RaceName = raceName;
        }

        public Bonus bonus1 = new Bonus(2"Bergbau");
        public Bonus bonus2 = new Bonus("Restlichtverstärker""30m sehen in Dunkelheit bei kleiner Lichtuelle");
        public Bonus bonus3 = new Bonus(2"Orientierung");
        public Bonus bonus4 = new Bonus(2"Schätzen");

       

        public void SetBonusList()
        {
            bonusArray[0] = bonus1;
            bonusArray[1] = bonus2;
            bonusArray[2] = bonus3;
            bonusArray[3] = bonus4;
        }

        public void SetAttributeList()
        {

            attributeArray[0] = str;
            attributeArray[1] = con;
            attributeArray[2] = dex;
            attributeArray[3] = per;
            attributeArray[4] = intel;
            attributeArray[5] = will;
            attributeArray[6] = cha;

        }



Die Übergabe funkioniert soweit nun, es wäre immer wieder Fehler da, die besagten das Felder oder Variablen null seien.

Genau, die Attribute legen sich pro "Rasse" eben anders fest und werden manuell als Feld nachgefüllt.
Da es ein fixes System ist, muss ich hier nicht dynamisch arbeiten sondern statisch.


Ich mach es vermutlich deshalb so kompliziert, weil ich es nicht besser weiß :(
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 19.09.12 22:48 
Lege die Eigenschaften wie z.B. Strengh doch in Race fest?

Das machst du dann also Eigenschaft, wo der set-Block mit protected geschützt wird.

ausblenden C#-Quelltext
1:
public Strengh str { get; protected set; }					


Das wäre dann automatisch und der Wert der Eigenschaft kann nur in der aktuellen Klasse oder allen erbenen Klassen genutzt werdem. Das macht das ganze sicherer und schadet nicht.

Du kannst auch Felder definieren und die dann in eine Eigenschaft kapseln. Das hat den Vorteil, dass du beim Lesen oder schreiben noch extra Code ausführen lassen kannst.

Als einfaches Beispiel:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
private string _Name;

public string Name
{
    get { return this._Name }
    protected set
    {
        if (value == nullthrow new ArgumentNullException();
        this._Name = value;
    }
}



Zitat:
Genau, die Attribute legen sich pro "Rasse" eben anders fest und werden manuell als Feld nachgefüllt.


Aber die Attribute sind für jede Klasse zwar anders aber dann auch fest?
Wenn dem so ist, dann definiere doch einfach in jeder erbenden Klasse noch einmal extra Eigenschaften, die Die der Race-Klasse so ergänzen, dass sie genau für die eigentliche Rasse dann passen.



Ach und noch was:

Instanziere den Wert einer Variable in einer Klasse lieber im Konstruktor.
Ich kann nicht sagen, was das für einenUnterschied macht, allerdings finde ich das schöner.
Bei den Eigenschaften brauchst du das aber nicht machen, denn da wird, soweit ich weiß, immer gleich ein default-Wert fest gelegt, wenn du nicht einen eigenen hinein schreibst. Daher gibt es bei Eigenschaften nicht das Problem, dass eine Variable nicht instanziert wurde.
Holger_S Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 19.09.12 22:53 
Super, danke für die Tips.

In der Tat wird es grade immer komplizierter und womöglich ist mein Konzept der Einfachheit grade zu einem großen unübersichtlichen Codeblock geworden :P
Dennoch Danke !
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 19.09.12 23:01 
Bei größeren Projekten lohnt es sich immer, vorher einen genau Plan anzulegen.

Aus meinem Umfeld weiß ich zwar, dass das nicht sonderlich beliebt ist, besonders weil es mehr ARbeit macht, aber glaub mir, es lohnt sich wirklich. ^^

Besonders wenn du eine komplexere Vererbungs-Hirarchie erschaffen willst oder sogar noch eine Datenbank mit einbaust.
Dann kommst du ohne gründliche Planung nicht sehr weit.