Eine Klassenhierarchie geometrischer Figuren

1. Aufgabe

Implementieren Sie eine Hierarchie mit Klassen, die zwei- und dreidimensionale geometrische Figuren repräsentieren. Bei den zweidimensionalen Figuren sollten ein Dreieck (Klasse Triangle), ein Viereck (Klasse Rectangle) und ein Kreis (Klasse Circle) nicht fehlen. Zu den dreidimensionalen Figuren gehören ein Würfel (Klasse Cube), eine Kugel (Klasse Sphere), ein Kegel (Klasse Cone) sowie ein Quader (Klasse Cuboid).

Überlegen Sie, welche Instanzvariablen zur Beschreibung der jeweiligen geometrischen Figur notwendig sind. Neben offensichtlichen Instanzvariablen wie der Radius eines Kreises oder die Seitenlänge eines Würfels soll jede Figur eine Positionsangabe besitzen, also einen x- und y-Wert für eine zweidimensionale Figur bzw. ein Tripel (x,y,z) bei einer dreidimensionalen Figur. Welcher Klasse in der Klassenhierarchie sind diese Positionsvariablen am besten zuzuordnen?

Konzipieren Sie für jede Klasse einen geeigneten Konstruktor. Ziehen Sie, soweit möglich, auch den Basisklassenkonstruktor bei der Erzeugung eines Objekts mit ein.

Klassenhierarchie geometrischer Figuren.

Abbildung 1. Klassenhierarchie geometrischer Figuren.


Überlegen Sie, welchen Klassen Sie die Eigenschaften Circumference (Umfang), Volume (Volumen), Area (Fläche) und Surface (Oberfläche) zuordnen können. Natürlich sollten alle Klassen eine Draw-Methode besitzen, um ein entsprechendes Objekt auf der Konsole zu „zeichnen“, sprich um seine relevanten Instanzvariablen auszugeben. Eine Methode MoveTo zur Positionsänderung ist ebenfalls zu realisieren. Die Programmausgabe studieren Sie am folgenden Codefragment:

Beispiel:

public static void Main()
{
    Triangle tria = new Triangle(1, 1, 2, 3, 4);
    tria.Draw();

    Rectangle rect = new Rectangle(10, 10, 20, 40);
    rect.Draw();

    Circle circle = new Circle(20, 20, 10);
    circle.Draw();

    Cube cube = new Cube(30, 30, 20, 10);
    cube.Draw();

    Cuboid cuboid = new Cuboid(50, 50, 40, 10, 20, 30);
    cuboid.Draw();

    Sphere sphere = new Sphere(40, 40, 30, 15);
    sphere.Draw();

    Cone cone = new Cone(60, 60, 50, 20, 30);
    cone.Draw();
}

Ausgabe:

Shape: Triangle
  TwoDimensional
  Position: 1,00, 1,00
    A: 2,00
    B: 3,00
    C: 4,00
    Area: 2,90
    Circumference: 9,00

Shape: Rectangle
  TwoDimensional
  Position: 10,00, 10,00
    Width: 20,00
    Height: 40,00
    Area: 800,00
    Circumference: 120,00

Shape: Circle
  TwoDimensional
  Position: 20,00, 20,00
    Radius: 10,00
    Area: 314,16
    Circumference: 62,83

Shape: Cube
  ThreeDimensional
  Position: 30,00, 30,00, 20,00
    Size: 10,00
    Volume: 1000,00
    Surface: 600,00

Shape: Cuboid
  ThreeDimensional
  Position: 50,00, 50,00, 40,00
    Width: 10,00
    Height: 20,00
    Depth: 30,00
    Volume: 6000,00
    Surface: 2200,00

Shape: Sphere
  ThreeDimensional
  Position: 40,00, 40,00, 30,00
    Radius: 15,00
    Volume: 14137,17
    Surface: 2827,43

Shape: Cone
  ThreeDimensional
  Position: 60,00, 60,00, 50,00
    Radius:  20,00
    Height:  30,00
    Volume:  12566,37
    Surface: 3522,07

2. Lösung

In den nachfolgenden Listings finden Sie der Reihe nach

  • den Entwurf der abstrakten Basisklasse Shape,

  • zwei Spezialisierungen für zwei- und dreidimensionale Figuren in Gestalt der Klassen TwoDimensional bzw. ThreeDimensional,

  • die Realisierungen der konkreten Klassen Triangle, Rectangle und Circle für zweidimensionale Figuren und schließlich

  • alle Realisierungen der konkreten Klassen Cube, Cuboid, Sphere und Cone für dreidimensionale Figuren

vor.

01: abstract class Shape : Object
02: {
03:     private String name;
04: 
05:     // c'tors
06:     public Shape() : this ("")
07:     {
08:     }
09: 
10:     public Shape (String name)
11:     {
12:         this.name = name;
13:     }
14: 
15:     // properties
16:     public String Name
17:     {
18:         get
19:         {
20:             return name;
21:         }
22:     }
23: 
24:     // public interface
25:     public virtual void Draw()
26:     {
27:         Console.WriteLine(this.ToString());
28:     }
29: 
30:     // overrides
31:     public override String ToString()
32:     {
33:         return String.Format("Shape: {0}", this.name);
34:     }
35: }

Beispiel 1. Konkrete Basisklasse Shape für alle Figuren.


01: abstract class TwoDimensional : Shape
02: {
03:     protected int x;
04:     protected int y;
05: 
06:     // c'tor
07:     protected TwoDimensional(String name, int x, int y)
08:         : base (name)
09:     {
10:         this.x = x;
11:         this.y = y;
12:     }
13: 
14:     // public interface
15:     public void MoveTo(int x, int y)
16:     {
17:         this.x = x;
18:         this.y = y;
19:     }
20: 
21:     // public contract for derived classes
22:     public abstract double Area { get; }
23:     public abstract double Circumference { get; }
24: 
25:     // overrides
26:     public override String ToString()
27:     {
28:         String s = base.ToString();
29:         s += Environment.NewLine; 
30:         s += "  TwoDimensional";
31:         s += Environment.NewLine;
32:         s += String.Format("  Position: {0:F2}, {1:F2}", this.x, this.y);
33:         s += Environment.NewLine;
34:         return s;
35:     }
36: }
37: 
38: abstract class ThreeDimensional : Shape
39: {
40:     protected int x;
41:     protected int y;
42:     protected int z;
43: 
44:     // c'tor
45:     protected ThreeDimensional(String name, int x, int y, int z)
46:         : base(name)
47:     {
48:         this.x = x;
49:         this.y = y;
50:         this.z = z;
51:     }
52: 
53:     // public interface
54:     public void MoveTo(int x, int y, int z)
55:     {
56:         this.x = x;
57:         this.y = y;
58:         this.z = z;
59:     }
60: 
61:     // public contract for derived classes
62:     public abstract double Volume { get; }
63:     public abstract double Surface { get; }
64:     
65:     // overrides
66:     public override String ToString()
67:     {
68:         String s = base.ToString();
69:         s += Environment.NewLine;
70:         s += "  ThreeDimensional";
71:         s += Environment.NewLine;
72:         s += String.Format("  Position: {0:F2}, {1:F2}, {2:F2}",
73:             this.x, this.y, this.z);
74:         s += Environment.NewLine;
75:         return s;
76:     }
77: }

Beispiel 2. Zwei abstrakte Spezialisierungen TwoDimensional und ThreeDimensional.


001: class Triangle : TwoDimensional
002: {
003:     private double a;
004:     private double b;
005:     private double c;
006: 
007:     // c'tor
008:     public Triangle(int x, int y, double a, double b, double c)
009:         : base("Triangle", x, y)
010:     {
011:         this.a = a;
012:         this.b = b;
013:         this.c = c;
014:     }
015: 
016:     // overrides
017:     public override double Area
018:     {
019:         get
020:         {
021:             return Math.Sqrt(((4.0 * this.a * this.a * this.c * this.c) -
022:             (this.a * this.a + this.c * this.c - this.b * this.b) *
023:             (this.a * this.a + this.c * this.c - this.b * this.b)) / 16.0);
024:         }
025:     }
026: 
027:     public override double Circumference
028:     {
029:         get
030:         {
031:             return this.a + this.b + this.c;
032:         }
033:     }
034: 
035:     // overrides
036:     public override String ToString()
037:     {
038:         String s = base.ToString();
039:         s += String.Format("    A: {0:F2}", this.a);
040:         s += Environment.NewLine;
041:         s += String.Format("    B: {0:F2}", this.b);
042:         s += Environment.NewLine;
043:         s += String.Format("    C: {0:F2}", this.c);
044:         s += Environment.NewLine;
045:         s += String.Format("    Area: {0:F2}", this.Area);
046:         s += Environment.NewLine;
047:         s += String.Format("    Circumference: {0:F2}", this.Circumference);
048:         s += Environment.NewLine;
049:         return s;
050:     }
051: }
052: 
053: class Rectangle : TwoDimensional
054: {
055:     protected int width;
056:     protected int height;
057: 
058:     // c'tor
059:     public Rectangle(int x, int y, int width, int height)
060:         : base("Rectangle", x, y)
061:     {
062:         this.width = width;
063:         this.height = height;
064:     }
065: 
066:     // properties
067:     public override double Area
068:     {
069:         get
070:         {
071:             return this.width * this.height;
072:         }
073:     }
074: 
075:     public override double Circumference
076:     {
077:         get
078:         {
079:             return 2 * (this.width + this.height);
080:         }
081:     }
082: 
083:     // overrides
084:     public override String ToString()
085:     {
086:         String s = base.ToString();
087:         s += String.Format("    Width: {0:F2}", this.width);
088:         s += Environment.NewLine;
089:         s += String.Format("    Height: {0:F2}", this.height);
090:         s += Environment.NewLine; 
091:         s += String.Format("    Area: {0:F2}", this.Area);
092:         s += Environment.NewLine;
093:         s += String.Format("    Circumference: {0:F2}", this.Circumference);
094:         s += Environment.NewLine; 
095:         return s;
096:     }
097: }
098: 
099: class Circle : TwoDimensional
100: {
101:     private double radius;
102: 
103:     // c'tor
104:     public Circle(int x, int y, double radius)
105:         : base("Circle", x, y)
106:     {
107:         this.radius = radius;
108:     }
109: 
110:     // overrides
111:     public override double Area
112:     {
113:         get
114:         {
115:             return this.radius * this.radius * Math.PI;
116:         }
117:     }
118: 
119: 
120:     public override double Circumference
121:     {
122:         get
123:         {
124:             return 2 * Math.PI * this.radius;
125:         }
126:     }
127: 
128:     // overrides
129:     public override String ToString()
130:     {
131:         String s = base.ToString();
132:         s += String.Format("    Radius: {0:F2}", this.radius);
133:         s += Environment.NewLine;
134:         s += String.Format("    Area: {0:F2}", this.Area);
135:         s += Environment.NewLine;
136:         s += String.Format("    Circumference: {0:F2}", this.Circumference);
137:         s += Environment.NewLine;
138:         return s;
139:     }
140: }

Beispiel 3. Konkrete zweidimensionale Klassen Triangle, Rectangle und Circle.


001: class Cube : ThreeDimensional
002: {
003:     private double size;
004: 
005:     // c'tor
006:     public Cube(int x, int y, int z, double size)
007:         : base("Cube", x, y, z)
008:     {
009:         this.size = size;
010:     }
011: 
012:     // overrides
013:     public override double Volume
014:     {
015:         get
016:         {
017:             return this.size * this.size * this.size;
018:         }
019:     }
020: 
021:     public override double Surface
022:     {
023:         get
024:         {
025:             return 6 * this.size * this.size;
026:         }
027:     }
028: 
029:     // overrides
030:     public override String ToString()
031:     {
032:         String s = base.ToString();
033:         s += String.Format("    Size: {0:F2}", this.size);
034:         s += Environment.NewLine;
035:         s += String.Format("    Volume: {0:F2}", this.Volume);
036:         s += Environment.NewLine;
037:         s += String.Format("    Surface: {0:F2}", this.Surface);
038:         s += Environment.NewLine;
039:         return s;
040:     }
041: }
042: 
043: class Cuboid : ThreeDimensional
044: {
045:     private double width;
046:     private double height;
047:     private double depth;
048: 
049:     // c'tor
050:     public Cuboid(
051:         int x, int y, int z,
052:         double width, double height, double depth)
053:         : base("Cuboid", x, y, z)
054:     {
055:         this.width = width;
056:         this.height = height;
057:         this.depth = depth;
058:     }
059: 
060:     // overrides
061:     public override double Volume
062:     {
063:         get
064:         {
065:             return this.width * this.height * this.depth;
066:         }
067:     }
068: 
069:     public override double Surface
070:     {
071:         get
072:         {
073:             return
074:                 2 *
075:                 (this.width * this.height +
076:                  this.height * this.depth +
077:                  this.depth * this.width);
078:         }
079:     }
080: 
081:     // overrides
082:     public override String ToString()
083:     {
084:         String s = base.ToString();
085:         s += String.Format("    Width: {0:F2}", this.width);
086:         s += Environment.NewLine;
087:         s += String.Format("    Height: {0:F2}", this.height);
088:         s += Environment.NewLine;
089:         s += String.Format("    Depth: {0:F2}", this.depth);
090:         s += Environment.NewLine;
091:         s += String.Format("    Volume: {0:F2}", this.Volume);
092:         s += Environment.NewLine;
093:         s += String.Format("    Surface: {0:F2}", this.Surface);
094:         s += Environment.NewLine;
095:         return s;
096:     }
097: }
098: 
099: class Sphere : ThreeDimensional
100: {
101:     private double radius;
102: 
103:     // c'tor
104:     public Sphere(int x, int y, int z, double radius)
105:         : base("Sphere", x, y, z)
106:     {
107:         this.radius = radius;
108:     }
109: 
110:     // overrides
111:     public override double Volume
112:     {
113:         get
114:         {
115:             return
116:                 (4.0 / 3.0) * Math.PI *
117:                 this.radius * this.radius * this.radius;
118:         }
119:     }
120: 
121:     public override double Surface
122:     {
123:         get
124:         {
125:             return 4 * Math.PI * this.radius * this.radius;    
126:         }
127:     }
128: 
129:     // overrides
130:     public override String ToString()
131:     {
132:         String s = base.ToString();
133:         s += String.Format("    Radius: {0:F2}", this.radius);
134:         s += Environment.NewLine;
135:         s += String.Format("    Volume: {0:F2}", this.Volume);
136:         s += Environment.NewLine;
137:         s += String.Format("    Surface: {0:F2}", this.Surface);
138:         s += Environment.NewLine;
139:         return s;
140:     }
141: }
142: 
143: class Cone : ThreeDimensional
144: {
145:     private double radius;
146:     private double height;
147: 
148:         // c'tor
149:     public Cone(int x, int y, int z, double radius, double height)
150:         : base("Cone", x, y, z)
151:     {
152:         this.radius = radius;
153:         this.height = height;
154:     }
155: 
156:     // overrides
157:     public override double Volume
158:     {
159:         get
160:         {
161:             return (Math.PI * this.radius * this.radius * this.height) / 3;
162:         }
163:     }
164: 
165:     public override double Surface
166:     {
167:         get
168:         {
169:             return
170:                 Math.PI * this.radius * (this.radius +
171:                 Math.Sqrt(this.height * this.height + this.radius * this.radius));
172:         }
173:     }
174: 
175:     // overrides
176:     public override String ToString()
177:     {
178:         String s = base.ToString();
179:         s += String.Format("    Radius:  {0:F2}", this.radius);
180:         s += Environment.NewLine;
181:         s += String.Format("    Height:  {0:F2}", this.height);
182:         s += Environment.NewLine;
183:         s += String.Format("    Volume:  {0:F2}", this.Volume);
184:         s += Environment.NewLine;
185:         s += String.Format("    Surface: {0:F2}", this.Surface);
186:         s += Environment.NewLine; 
187:         return s;
188:     }
189: }

Beispiel 4. Konkrete dreidimensionale Klassen Cube, Cuboid, Sphere und Cone.