Ö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.
Görev
KolaySomut 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ış birString channelözelliğine,[channel]: [message]yazdıran birsend(String message)metoduna ve'Notification ready'dizesini döndüren birgetStatus()metoduna sahip birNotificationsınıfı.Notificationsınıfını uygulayan (implements) birEmailNotificationsınıfı.implementskullandığınız için kendichannelözelliğinizi sağlamalısınız (değerini'email'yapın),Sending email: [message]yazdıran kendisend()metodunuzu ve'Email service active'döndüren kendigetStatus()metodunuzu yazmalısınız.Notificationsınıfını uygulayan (implements) birPushNotificationsınıfı.channeldeğerini'push'olarak ayarlayın,send()metodununPush alert: [message]yazdırmasını sağlayın vegetStatus()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
EmailNotificationve birPushNotificationörneği oluşturun. - Her bildirim için
getStatus()kullanarak durumunu yazdırın, ardından'Hello World'mesajıylasend()metodunu çağırın. - İki bildirim arasında boş bir satır yazdırın.
- Bir
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 WorldKopya 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
}
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
1OOP Temelleri
Harici DosyalarKütüphaneler ve ImportlarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarÖrnek DeğişkenleriConstructor TemelleriÖzet - Basit Hesap Makinesi4Null Safety
Null Safety'ye GirişNullable ve Non-Nullable? ve ! OperatörleriLate Anahtar Kelimesi ve Null SafetyNull-Aware OperatörleriSınıflarda Null SafetyÖzet - Kullanıcı Profili Sistemi7Soyut Sınıflar ve Arayüzler
Soyut SınıflarSoyut MetotlarDart'ta ArayüzlerÖrtük ArayüzlerUygulama vs. GenişletmeÇoklu ArayüzlerÖzet - Şekil Hesaplayıcı10Koleksiyonlar ve Generic'ler
List, Set, Map Genel BakışTip Güvenli KoleksiyonlarGeneric SınıflarGeneric MetotlarGeneric KısıtlamalarIterable ve IteratorÖzet - Generic Depolama2Dart'ta Yapıcılar
Varsayılan Yapıcıİsimlendirilmiş Yapıcılarİlklendirme ListeleriSabit YapıcılarFabrika YapıcılarıYönlendiren YapıcılarÖzet - Şekil Oluşturucu5Kapsülleme
Public ve Private Üyeler_ Öneki KuralıKütüphane Düzeyinde GizlilikGetter ve Setter DetaylarıBilgi GizlemeÖzet - Öğrenci Kayıtları8Mixin'ler
Mixin'lere GirişMixin OluşturmaBirden Fazla Mixin KullanımıMixin'lerde on Anahtar KelimesiMixin vs KalıtımMixin vs ArayüzÖzet - Hayvan Sistemi11Özel Metotlar
toString() OverridehashCode ve == OverrideComparable Arayüzücall() MetodunoSuchMethod OverrideÖzet - Özel Koleksiyon14Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı17Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakter SistemiAraç Kiralama Servisi3Sınıf Özellikleri
Instance ve Statik ÜyelerFinal ve Const AlanlarLate DeğişkenlerStatik Metotlar ve AlanlarGetters ve SettersÖzet - Banka Hesabı Yöneticisi6Kalıtım
Temel Kalıtımsuper Anahtar KelimesiMetot Ezme@override Anotasyonufinal Sınıf Anahtar KelimesiYapıcı Metotlar ve KalıtımÖzet - Çalışan Hiyerarşisi9Çok Biçimlilik
Çok Biçimlilik TemelleriInterface'ler ile Çok BiçimlilikÇalışma Zamanı Tip Kontrolüis ve as OperatörleriCovariant Anahtar KelimesiÖzet - Ödeme İşlemcisi12Asenkron OOP
Futures ve async/awaitStream TemelleriStream Controller'larAsenkron KurucularSınıf Metotlarında Asenkron KullanımıÖzet - Data Fetcher15Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıRepository Kalıbı