Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Wykład 5

Interfejsy

dr inż. Maciej Kusy

Katedra Podstaw Elektroniki

Wydział Elektrotechniki i Informatyki

Politechnika Rzeszowska

Programowanie w języku C#

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Plan wykładu

• Pojęcie interfejsu, właściwości interfejsów

• Definiowanie i implementowanie interfejsu

• Implementacja kilku interfejsów

• Łączenie i rozszerzanie interfejsu

• Dostęp do metod interfejsu

• Rzutowanie na interfejs

• Operator is i operator as

• Interfejsy kontra klasy abstrakcyjne

• Przesłanianie implementacji interfejsu

• Jawna implementacja interfejsu

2

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Interfejs

Interfejs to nazwa grupy metod. Z perspektywy interfejsu nie jest ważna definicja tych metod – ważna jest tylko ich sygnatura: (nazwa, argumenty) oraz typ wartości zwracanej.

Interfejs definiuje zachowanie klasy – można to ująć

słowami: „ potrafi robić” – jest to relacja implementacji.

W definicji interfejsu, można podać deklaracje metody, właściwości, mechanizmu indeksującego (indeksera) lub

zdarzenia.

Interfejs nie może natomiast zawierać deklaracji żadnych pól!

3

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Właściwości interfejsów:

• Interfejs nie może dziedziczyć po klasie.

• Interfejs może rozszerzać wiele interfejsów.

• Klasa może implementować wiele interfejsów (ale może dziedziczyć tylko po jednej klasie).

• Żadna z metod zadeklarowanych w interfejsie nie może mieć nim w implementacji.

• Przy deklaracji składowej interfejsu nie używamy

modyfikatora dostępu – składowe interfejsu są publiczne.

• Przy deklaracjach składowych nie można również użyć innych modyfikatorów, tj.: virtual, abstract, override.

• Nazwa interfejsu powinna rozpoczynać się od litery I (konwencja).

• Implementacja interfejsu polega na zdefiniowaniu wszystkich jego składowych w klasie, która go implementuje.

4

• Struktury mogą implementować interfejsy.

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Definicja i implementacja interfejsu

interface IPrzechowalnia

{

void Zapisz();

}

class Dokument : IPrzechowalnia

{

public Dokument() {/*...*/}

public void Zapisz()

{

//Ciało metody

}

}

5

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Implementacja kilku interfejsów

interface IA

{

void WypiszA();

}

interface IB

{

void WypiszB();

}

class C : IA, IB

{

public void WypiszA(){/*... */}

public void WypiszB(){/*... */}

}

6

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Łączenie i rozszerzanie interfejsów

interface IA { void MetodaA(); }

interface IB { void MetodaB(); }

interface IC { void MetodaC(); }

interface ID : IA, IB { void MetodaD(); }

class E : IC, ID

{

public void MetodaC(){/*... */}

public void MetodaA(){/*... */}

public void MetodaB(){/*... */}

public void MetodaD(){/*... */}

}

7

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Dostęp do metod interfejsu

Można stworzyć egzemplarz interfejsu rzutując go na dany typ.

Odpowiednią referencję wskazującą na obiekt implementujący interfejs:

Dokument dok = new Dokument();

IPrzechowalnia iDok = dok;

iDok.Zapisz();

IPrzechowalnia iDok2 = new Dokument();

Nie można bezpośrednio stworzyć egzemplarza interfejsu: IPrzechowlania iDok3 = new IPzechowalnia();

8

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Rzutowanie na interfejs

Często nie wiadomo, czy typ (klasa) implementuje dany

interfejs.

W takich wypadkach należy zrzutować obiekt klasy na

dany interfejs:

Dokument dok = new Dokument();

IPrzechowalnia iDok = (IPrzechowalnia) dok;

iDok.Zapisz();

W przypadku gdy klasa nie implementuje interfejsu,

rzutowanie jest niepoprawne i zostanie zgłoszony wyjątek: System.InvalidCastException.

Jak to bezpiecznie sprawdzić? Zastosować operator is.

9

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Operator is

Aby wywołać odpowiednią metodę interfejsu na rzecz obiektu, należy sprawdzić, czy klasa tego obiektu implementuje dany interfejs. Jednym z rozwiązań jest zastosowanie operatora is: Dokument dok = new Dokument();

if(dok is IPrzechowlania)

{

IPrzechowalnia iDok = (IPrzechowalnia) dok;

}

Operator is zwraca true jeżeli wyrażenie w instrukcji if (musi być typem referencyjnym) można bezpiecznie rzutować bez zgłoszenia wyjątku.

10

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Operator as

Operator as jest rozszerzeniem operatora is – sprawdza czy dane rzutowanie jest dozwolone (czyli czy operator is zwraca true) i jeżeli warunek jest spełniony – wykonuje rzutowanie.

Dokument dok = new Dokument();

IPrzechowalnia iDok = dok as IPrzechowalnia;

if(iDok != null)

{

//rzutowanie jest dozwolone

}

Operator as eliminuje potrzebę obsługi wyjątku. Jeżeli adres egzemplarza interfejsu jest różny od adresu zerowego, to rzutowanie jest możliwe, bo dana klasa implementuje interfejs.

11

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Interfejsy kontra klasy abstrakcyjne

• Interfejs definiuje zachowanie klasy („ potrafi robić”), klasa pochodna po klasie abstrakcyjnej jest „ tego samego typu”, co jej klasa bazowa.

• Interfejsy w przeciwieństwie do klas abstrakcyjnych dają możliwość wielokrotnego rozszerzania (dziedziczenia).

• Dodanie nowej metody do interfejsu wiąże się z

koniecznością dostosowania wszystkich klas, które ten

interfejs implementują.

• Dodanie nowej metody do abstrakcyjnej klasy bazowej nie wprowadza żadnego zamieszania – wystarczy nową metodę

zadeklarować jako wirtualną z domyślną implementacją.

• Jeżeli klasa dziedziczy po jakiejś klasie i implementuje kilka interfejsów, to nazwa klasy musi wystąpić jako

pierwsza na liście dziedziczenia.

12

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Przesłanianie implementacji interfejsu

W klasie obsługującej interfejs, metody interfejsu można oznaczyć jako wirtualne.

W klasach pochodnych można wtedy przesłaniać

implementacje tych metod.

Dzięki temu możliwe jest używanie metod klas w hierarchii dziedziczenia w sposób polimorficzny za pomocą obiektu interfejsu.

13

Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl Jawna implementacja interfejsu

Co dzieje się w przypadku, gdy klasa implementuje kilka interfejsów, w których znajdują się metody o tej samej nazwie?

interface IA { void Metoda(); }

interface IB { void Metoda(); }

class C : IA, IB {/* ??? */}

Odpowiedź: w klasie musi znaleźć się jawna implementacja każdej z metod:

class C : IA, IB

{

void IA.Metoda(){} //metoda niejawnie publiczna void IB.Metoda(){} //nie można użyć mod. public

}

14