Klasy i metody abstrakcyjne

Stronę tą wyświetlono już: 234 razy

Wstęp

Chociaż interfejsy w wielu przypadkach są wystarczające, jednakże czasami trzeba użyć klas abstrakcyjnych, czyli takich, których instancji obiektu nie da się utworzyć bezpośrednio, nawet jeżeli metody takiej klasy nie są abstrakcyjne. Jest to istotne, ponieważ interfejsy umożliwiają jedynie zaznaczenie, jakie metody muszą obsługiwać klasy po nich dziedziczące.

Przykładowa implementacja klasy abstrakcyjnej

Oto prosty przykład klasy abstrakcyjnej:

Listing 1
  1. public abstract class aGeometryObj
  2. {
  3. public string object_name;
  4. public aGeometryObj()
  5. {
  6. object_name = "";
  7. }
  8. public aGeometryObj(string object_name)
  9. {
  10. this.object_name = object_name;
  11. }
  12. public double Length { get; set; }
  13. public abstract override string ToString();
  14. public double X { get; set; }
  15. public double Y { get; set; }
  16. }
  17. // ########################### DEKLARACJA KLASY POINT@D #############################
  18. public class Point2D : aGeometryObj//, IPoint2D
  19. {
  20. // ####################### CHRONIONE POLA KLASY #################################
  21. protected double x;
  22. protected double y;
  23. // ####################### KONSTRUKTORY KLASY ###################################
  24. public Point2D() // konstruktor zerujący
  25. : base("Początek układu współrzędnych")
  26. {
  27. x = y = 0;
  28. }
  29. public Point2D(double x, double y) // konstruktor ustawiajacy
  30. {
  31. this.x = x;
  32. this.y = y;
  33. }
  34. public Point2D(Point2D p) // kosntruktor kopiujący
  35. {
  36. this.x = p.x;
  37. this.y = p.y;
  38. }
  39. // ######## WŁAŚCIWOŚCI KLASY ##########
  40. public new double Y
  41. {
  42. get { return y; }
  43. set {
  44. y = value;
  45. if( y == 0 && x == 0){
  46. this.object_name = "Początek układu współrzędnych";
  47. }
  48. }
  49. }
  50. public new double X
  51. {
  52. get { return x; }
  53. set {
  54. x = value;
  55. if( y == 0 && x == 0){
  56. this.object_name = "Początek układu współrzędnych";
  57. }
  58. }
  59. }
  60. public new double Length
  61. {
  62. get { return Math.Sqrt(x * x + y * y); } // pobieranie długości wektora
  63. set // ustawianie długości wektora
  64. {
  65. if (x != 0 || y != 0) // gdy wektor nie jest zerowy to
  66. {
  67. double k = value / Length;
  68. x *= k; // skalowanie składowej x wektora
  69. y *= k; // skalowanie składowej y wektora
  70. }
  71. }
  72. }
  73. // ########### METODY #############
  74. public override string ToString() // przeładowana metoda ToString klasy bazowej Object
  75. {
  76. return "Point2D x = " + x + "; y = " + y;
  77. }
  78. }
  79. // ############################## DEKLARACJA KLASY POINT3D #################################
  80. public class Point3D : Point2D, Klasy.IPoint3D // dziedziczy po Point2D
  81. {
  82. // ########################## CHRONIONE POLA KLASY #####################################
  83. protected double z;
  84. // ########################## KONSTRUKTORY KLASY #######################################
  85. public Point3D()
  86. : base() // wywołanie bezparametrowego kosntruktora klasy bazowej
  87. {
  88. z = 0;
  89. }
  90. public Point3D(double x, double y, double z)
  91. : base(x, y) // wywołanie ustawiającego konstruktora klasy bazowej
  92. {
  93. this.z = z;
  94. }
  95. public Point3D(Point3D p) // konstruktor kopiujący
  96. : base(p) // wywołanie kontruktora kopiującego klasy bazowej
  97. {
  98. z = p.z;
  99. }
  100. // ################# WŁAŚCIWOŚCI ###############
  101. public double Z
  102. {
  103. get { return z; }
  104. set { z = value; }
  105. }
  106. public new double Length // przysłanianie właściwości z klasy bazowej (oznacza to słowo kluczowe new)
  107. {
  108. get { return Math.Sqrt(x * x + y * y + z * z); } // pobieranie długości wektora
  109. set // ustawianie długości wektora
  110. {
  111. if (x != 0 || y != 0 || z != 0)
  112. {
  113. double k = value / Length;
  114. X *= k;
  115. Y *= k;
  116. z *= k;
  117. }
  118. }
  119. }
  120. // ################# METODY ################
  121. public new string ToString() // przysłanianie metody z klasy bazowej (oznacza to słowo kluczowe new)
  122. {
  123. return "Point3D x = " + X + "; y = " + Y + "; z = " + z;
  124. }
  125. }

W powyższym kodzie klasa abstrakcyjna aGeometryObj ma publiczne pole object_name, zaimplementowane na wypadek, gdyby ktoś zażyczył sobie stworzyć jakiś obiekt geometryczny o szczególnych cechach, który zostałby opisany nazwą własną. Takim obiektem może być np. punkt 2W lub 3W. Trochę na wyrost umieściłem tutaj metody oraz właściwości klasy, które zostały zaimplementowane wcześniej w interfejsie IPoint2D, ale to tylko po to aby pokazać, że można tutaj umieszczać również funkcje i właściwości klas. Teraz korzystając z powyższych klas, mogę zrobić coś takiego:

Listing 2
  1. aGeometryObj[] t = new aGeometryObj[2];
  2. t[0] = new Point2D(100, 200);
  3. t[1] = new Point3D(20, 30, 40);
  4. foreach (aGeometryObj p2 in t)
  5. {
  6. if (p2 is Point3D)
  7. {
  8. Console.WriteLine(((Point3D)p2).ToString());
  9. }
  10. else
  11. {
  12. Console.WriteLine(p2.ToString());
  13. }
  14. }
  15. Console.ReadLine();

Wynik działania:

Point2D x = 100; y = 200
Point3D x = 20; y = 30; z = 40

Czyli to samo co poprzednio, ale poprzednio nie mogłem zrobić czegoś takiego:

Listing 3
  1. aGeometryObj[] t = new aGeometryObj[2];
  2. t[0] = new Point2D(100, 200);
  3. t[0].object_name = "Punkt 2W - tutaj zaczepię środek ciężkości trójkąta";
  4. t[1] = new Point3D(20, 30, 40);
  5. t[1].object_name = "Punkt 3W - tutaj będzie środek ciężkości jakiejś bryły przestrzennej";
  6. foreach (aGeometryObj p2 in t)
  7. {
  8. if (p2 is Point3D)
  9. {
  10. Console.WriteLine(((Point3D)p2).ToString());
  11. }
  12. else
  13. {
  14. Console.WriteLine(p2.ToString());
  15. }
  16. Console.WriteLine(p2.object_name);
  17. }
  18. Console.ReadLine();

Wynik działania tego kodu jest następujący:

Point2D x = 100; y = 200
Punkt 2W - tutaj zaczepię środek ciężkości trójkąta
Point3D x = 20; y = 30; z = 40
Punkt 3W - tutaj będzie środek ciężkości jakiejś bryły przestrzennej

Komentarze