Od wersji 8.0 interfejs może posiadać także posiadać domyślną implementację metody jak i kilka innych nowości.
Zacznijmy od domyślnej implementacji metody. Dla programistów Javy nie jest to nowość - domyślna implementacja metody istnieje od wersji 8 Javy. Można by powiedzieć, że C# także to umożliwia od wersji 8.0 (przypadek :) ? ). Spójrzmy na przykładowy interfejs:
public interface IFile { void SaveFile(string filePath, string fileContent); }
Powyższy interfejs zgodnie z nazwą powinien pozwalać operować na plikach. Obecnie posiada jedną metodę - SaveFile która pozwala zapisać plik. Jak wiadomo na plikach można wykonać znacznie więcej operacji. Od klienta przychodzi nowe zlecenie - proszę udostępnić operację odczytu pliku. Nic prostszego - stwierdzamy, że nie ma sensu męczyć osoby implementujące nasz interfejs i dodajemy do niego nową metodę z domyślną implementacją. W taki oto sposób powstaje kod:
public interface IFile { void SaveFile(string filePath, string fileContent); string ReadFile(string filePath) { return File.ReadAllText(filePath); } } public class SystemFile : IFile { public void SaveFile(string filePath, string fileContent) { File.WriteAllText(filePath, fileContent); } }
Użycie:
IFile file = new SystemFile(); file.ReadFile("pathToFile");
Jeżeli używamy słowa kluczowego var podczas deklarowania typu obiektu należy pamiętać o tym, że typ SystemFile nie zawiera implementacji metody ReadFile. Mamy dwa wyjścia: jawnie zadeklarować typ jak powyżej, bądź rzutować tworzony obiekt na interfejs.
Wydawałoby się, że domyślna implementacja jest wręcz rewelacyjną wiadomością dla programistów C#. Już nie musimy martwić się, że dodając nową operację do interfejsu nasi klienci otrzymają błąd kompilacji. Ale czy tak na pewno jest?
Powyższe rozumowanie należy uzupełnić o potencjalne problemy wynikające z stosowania tego rozwiązania. Aby to pokazać dodam drugą implementację naszego interfejsu:
public class AwsFile : IFile { public void SaveFile(string filePath, string fileContent) { var s3Client = new AmazonS3Client(RegionEndpoint.EUCentral1); var fileTransferUtility = new TransferUtility(s3Client); fileTransferUtility.Upload(filePath, "bucketName"); } }
Jak widać sprawa się komplikuje. Klasa AwsFile pozwala zapisać plik w AWS.S3. Trudno sobie wyobrazić, że implementacja domyślna działająca na systemie plików pozwoli odczytać dane także w S3. Nie jest to możliwe - użytkownik prawdopodobnie otrzyma błąd. Należy więc przemyśleć czy każda domyślna implementacja ma faktycznie sens i jest na tyle uniwersalna aby ją udostępnić naszym klientom. Zauważyć można, że aż do wersji 8 nie posiadaliśmy domyślnej implementacji i doskonale sobie bez niej radziliśmy. Warto więc przemyśleć kiedy ma to sens a kiedy nie.
Oprócz powyższej zmiany interfejsy obecnie pozwalają na deklarowanie pól, statycznych sygnatur elementów interfejsu jak i stosowanie dowolnego modyfikatora dostępu (tak, tak już na rekrutacji nie trzeba bać się pytania "jaki modyfikator posiadają elementy interfejsu" :)).
public interface IFile { void SaveFile(string filePath, string fileContent); string ReadFile(string filePath) { return File.ReadAllText(filePath); } private static void DoSomething() { } protected static void DoSomething2() { } private static string defaultPath; public static void SetDefaultPath(string path) { defaultPath = path; } }
Jak widać sporo zmian. Podsumowując od wersji 8.0 C# umożliwia następujące nowości dla interfejsów:- domyślna implementacja metod
- możliwość deklaracji pól
- statyczne elementy
- dodawanie modyfikatorów dostępu
Brak komentarzy:
Prześlij komentarz