Menu
Coddy logo textTech

Örtük Arayüzler

Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 46 / 110.

Her Dart sınıfı otomatik olarak bir arayüz tanımladığından, herhangi bir sınıfı bir arayüz olarak kullanabilirsiniz - tam uygulamalara sahip somut sınıfları bile. Buna örtük arayüz (implicit interface) diyoruz.

Özellikleri ve metotları olan bir sınıfı düşünün:

class Logger {
  String prefix = '[LOG]';
  
  void log(String message) {
    print('$prefix $message');
  }
  
  void clear() {
    print('Clearing logs...');
  }
}

Başka bir sınıf Logger arayüzünü uyguladığında, prefix özelliği de dahil olmak üzere her şey için kendi uygulamasını sağlamalıdır:

class FileLogger implements Logger {
  @override
  String prefix = '[FILE]';
  
  @override
  void log(String message) {
    print('$prefix Writing to file: $message');
  }
  
  @override
  void clear() {
    print('Deleting log file...');
  }
}

Temel içgörü şudur: implements kullandığınızda, "sınıfım aynı şekle sahip olacak" -yani aynı metotlara ve özelliklere- demiş olursunuz. Herhangi bir kod, yapıcı (constructor) veya varsayılan değer miras almazsınız. Sadece arayüzün (interface) yapısına uymayı taahhüt ediyorsunuz.

Bu, örtük arayüzleri (implicit interfaces) değiştirilebilir bileşenler oluşturmak için güçlü kılar. Bir Logger bekleyen kod, bu uygulamanın dahili olarak nasıl çalıştığına bakılmaksızın, onun arayüzünü uygulayan herhangi bir sınıfla çalışabilir.

challenge icon

Görev

Kolay

Somut sınıfların nasıl örtük arayüzler (implicit interfaces) olarak hizmet edebileceğini gösteren bir bildirim sistemi oluşturalım. Temel bir bildirim sınıfı oluşturacak ve ardından bunu tamamen farklı bir şekilde uygulayacaksınız; bu, implements anahtar kelimesinin tüm üyeleri kendinizin sağlamasını gerektirdiğini gösterecektir.

Kodunuzu iki dosyada organize edeceksiniz:

  • notification.dart: Bildirim sınıflarınızı burada tanımlayın:
    • 'default' değerine ayarlanmış bir String channel özelliğine, [channel]: [message] yazdıran bir send(String message) metoduna ve 'Notification ready' dizesini döndüren bir getStatus() metoduna sahip bir Notification sınıfı.
    • Notification sınıfını uygulayan (implements) bir EmailNotification sınıfı. implements kullandığınız için kendi channel özelliğinizi sağlamalısınız (değerini 'email' yapın), Sending email: [message] yazdıran kendi send() metodunuzu ve 'Email service active' döndüren kendi getStatus() metodunuzu yazmalısınız.
    • Notification sınıfını uygulayan (implements) bir PushNotification sınıfı. channel değerini 'push' olarak ayarlayın, send() metodunun Push alert: [message] yazdırmasını sağlayın ve getStatus() metodunun 'Push service connected' döndürmesini sağlayın.
  • main.dart: Bildirim dosyanızı içe aktarın ve farklı sınıfların aynı örtük arayüzü tamamen farklı davranışlarla nasıl uygulayabileceğini gösterin:
    • Bir EmailNotification ve bir PushNotification örneği oluşturun.
    • Her bildirim için getStatus() kullanarak durumunu yazdırın, ardından 'Hello World' mesajıyla send() metodunu çağırın.
    • İki bildirim arasında boş bir satır yazdırın.

Unutmayın: implements kullandığınızda, Notification sınıfından herhangi bir kod miras almazsınız. Sadece sınıfınızın aynı şekle (aynı özelliklere ve metodlara) sahip olacağına dair söz verirsiniz. Uygulayan her sınıf kendi tam uygulamasını sağlar.

Beklenen çıktı:

Email service active
Sending email: Hello World

Push service connected
Push alert: Hello World

Kopya kağıdı

Dart'ta her sınıf otomatik olarak bir örtük arayüz (implicit interface) tanımlar. Bu, tam uygulamalara sahip somut sınıflar da dahil olmak üzere herhangi bir sınıfı bir arayüz olarak kullanabileceğiniz anlamına gelir.

Bir sınıf implements anahtar kelimesini kullandığında, arayüzdeki tüm özellikler ve yöntemler için kendi uygulamasını sağlamalıdır. Herhangi bir kod, kurucu (constructor) veya varsayılan değer miras almazsınız; yalnızca arayüzün yapısına uymayı taahhüt edersiniz.

Somut bir sınıf örneği:

class Logger {
  String prefix = '[LOG]';
  
  void log(String message) {
    print('$prefix $message');
  }
  
  void clear() {
    print('Clearing logs...');
  }
}

Örtük arayüzü uygulama:

class FileLogger implements Logger {
  @override
  String prefix = '[FILE]';
  
  @override
  void log(String message) {
    print('$prefix Writing to file: $message');
  }
  
  @override
  void clear() {
    print('Deleting log file...');
  }
}

Bu, örtük arayüzleri birbirinin yerine geçebilen bileşenler oluşturmak için güçlü kılar. Bir Logger bekleyen kod, dahili uygulamadan bağımsız olarak, onun arayüzünü uygulayan herhangi bir sınıfla çalışabilir.

Kendin dene

import 'notification.dart';

void main() {
  // TODO: Bir EmailNotification örneği oluşturun
  
  // TODO: getStatus() kullanarak e-posta bildiriminin durumunu yazdırın
  
  // TODO: E-posta bildirimini kullanarak 'Hello World' mesajı gönderin
  
  // TODO: Boş bir satır yazdırın
  
  // TODO: Bir PushNotification örneği oluşturun
  
  // TODO: getStatus() kullanarak anlık bildirimin durumunu yazdırın
  
  // TODO: Anlık bildirimi kullanarak 'Hello World' mesajı gönderin
  
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler