Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 2164 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:

interface IPoint2D { double Length { get; set; } string ToString(); double X { get; set; } double Y { get; set; } }

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:

interface IPoint2D { double Length { get; set; } string ToString(); double X { get; set; } double Y { get; set; } } interface IPoint3D : IPoint2D { new double Length { get; set; } new string ToString(); double Z { get; set; } } // ########################### DEKLARACJA KLASY POINT@D ############################# public class Point2D : IPoint2D { // ####################### CHRONIONE POLA KLASY ################################# protected double x; protected double y; // ####################### KONSTRUKTORY KLASY ################################### public Point2D() // konstruktor zerujący { x = y = 0; } public Point2D(double x, double y) // konstruktor ustawiajacy { this.x = x; this.y = y; } public Point2D(Point2D p) // kosntruktor kopiujący { this.x = p.x; this.y = p.y; } // ######## WŁAŚCIWOŚCI KLASY ########## public double Y { get { return y; } set { y = value; } } public double X { get { return x; } set { x = value; } } public double Length { get { return Math.Sqrt(x * x + y * y); } // pobieranie długości wektora set // ustawianie długości wektora { if (x != 0 || y != 0) // gdy wektor nie jest zerowy to { double k = value / Length; x *= k; // skalowanie składowej x wektora y *= k; // skalowanie składowej y wektora } } } // ########### METODY ############# public override string ToString() // przeładowana metoda ToString klasy bazowej Object { return "Point2D x = " + x + "; y = " + y; } } // ############################## DEKLARACJA KLASY POINT3D ################################# public class Point3D : Point2D, IPoint3D // dziedziczy po Point2D { // ########################## CHRONIONE POLA KLASY ##################################### protected double z; // ########################## KONSTRUKTORY KLASY ####################################### public Point3D() : base() // wywołanie bezparametrowego kosntruktora klasy bazowej { z = 0; } public Point3D(double x, double y, double z) : base(x, y) // wywołanie ustawiającego konstruktora klasy bazowej { this.z = z; } public Point3D(Point3D p) // konstruktor kopiujący : base(p) // wywołanie kontruktora kopiującego klasy bazowej { z = p.z; } // ################# WŁAŚCIWOŚCI ############### public double Z { get { return z; } set { z = value; } } public new double Length // przysłanianie właściwości z klasy bazowej (oznacza to słowo kluczowe new) { get { return Math.Sqrt(x * x + y * y + z * z); } // pobieranie długości wektora set // ustawianie długości wektora { if (x != 0 || y != 0 || z != 0) { double k = value / Length; X *= k; Y *= k; z *= k; } } } // ################# METODY ################ public new string ToString() // przysłanianie metody z klasy bazowej (oznacza to słowo kluczowe new) { return "Point3D x = " + X + "; y = " + Y + "; z = " + z; } }

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

namespace Klasy { class Program { static void Main(string[] args) { IPoint2D[] t = new IPoint2D[2]; t[0] = new Point2D(100, 200); t[1] = new Point3D(20, 30, 40); foreach (IPoint2D p in t) { if (p is Point3D) { Console.WriteLine(((Point3D)p).ToString()); } else { Console.WriteLine(p.ToString()); } } Console.ReadLine(); } } }

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.

Layout wykonany przez autora strony, wszelkie prawa zastrzeżone. Jakiekolwiek użycie części lub całości grafik znajdujących się na tej stronie bez pisemnej zgody jej autora surowo zabronione.