Interfejsy

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

Interfejsy działają w pewnym stopni jak klasy abstrakcyjne w C++, jednakże interfejsy ograniczają się do deklaracji metod i właściwości, które klasa dziedzicząca po takim interfejsie musi obsłużyć. Oto prosty przykład interfejsu:

Listing 1
  1. interface IPoint2D
  2. {
  3. double Length { get; set; }
  4. string ToString();
  5. double X { get; set; }
  6. double Y { get; set; }
  7. }

Teraz, jeżeli w kodzie programu utworzę klasę dziedziczącą po interfejsie IPoint2D, to taka klasa musi obsłużyć wszystkie metody i właściwości, zadeklarowane w tymże interfejsie. Poniżej zamieszczam przykład implementacji dwóch interfejsów i dwóch klas po nich dziedziczących:

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

Przykład zastosowanie interfejsów do przechowywania różnych zmiennych w jednej tablicy:

Listing 3
  1. namespace Klasy
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. IPoint2D[] t = new IPoint2D[2];
  8. t[0] = new Point2D(100, 200);
  9. t[1] = new Point3D(20, 30, 40);
  10. foreach (IPoint2D p in t)
  11. {
  12. if (p is Point3D)
  13. {
  14. Console.WriteLine(((Point3D)p).ToString());
  15. }
  16. else
  17. {
  18. Console.WriteLine(p.ToString());
  19. }
  20. }
  21. Console.ReadLine();
  22. }
  23. }
  24. }

Wynik działania powyższego kodu:

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

Nic nie stoi na przeszkodzie, aby utworzyć metodę klasy, która będzie przyjmowała jako argument dany interfejs. W takim przypadku każdy obiekt klasy, która dziedziczy po owym interfejsie będzie mógł zostać przekazany jako parametr takiej metody.

Komentarze