Mixin ve Arayüz Karşılaştırması
Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 55 / 110.
Mixin'lerin kalıtımla nasıl karşılaştırıldığını gördün. Şimdi, her ikisi de birden fazla türle çalışmana olanak tanıdığı için mixin'leri arayüzlerle karşılaştıralım. Temel fark, sağladıkları şeydir: arayüzler bir sözleşme tanımlarken mixin'ler uygulama sağlar.
Bir arayüzü uyguladığınızda belirli metotları sağlama sözü verirsiniz, ancak tüm kodu kendiniz yazarsınız. Bir mixin kullandığınızda ise gerçek kodu ücretsiz olarak elde edersiniz.
// Arayüz yaklaşımı - her şeyi uygulamanız gerekir
abstract class Printable {
void printInfo();
}
class Report implements Printable {
@override
void printInfo() {
print('Printing report...'); // Bunu siz yazarsınız
}
}
// Mixin yaklaşımı - uygulama dahildir
mixin Printable {
void printInfo() {
print('Printing...'); // Sizin için zaten yazıldı
}
}
class Report with Printable {} // printInfo() işlevini otomatik olarak alırÖyleyse her birini ne zaman kullanmalısınız? Farklı sınıfların aynı yöntem imzalarına ancak farklı uygulamalara ihtiyaç duyduğu durumlarda bir arayüz kullanın. Sınıfların tamamen aynı davranışı paylaşması gerektiğinde ise bir mixin kullanın.
| Özellik | Arayüz | Mixin |
|---|---|---|
| Sağladığı | Yalnızca sözleşme | Sözleşme + kod |
| Uygulama | Sen yazarsın | Dahil |
| Anahtar kelime | implements | with |
| Şunlar için en iyisi | Farklı davranışlar, aynı API | Paylaşılan davranış |
Hatta her iki yaklaşımı birleştirebilirsin: bir sınıfın neler yapabileceğini tanımlamak için arayüzleri, uygun olduğunda ortak uygulamalar sağlamak için mixin'leri kullanabilirsin. Dart'ta her ikisini birleştirirken her zaman with ifadesini implements ifadesinden önce yaz:
class MyClass with SomeMixin implements SomeInterface {
// with, implements'tan önce gelir
}Görev
KolayArayüzlerin ve mixin'lerin ne zaman kullanılacağını gösteren bir bildirim sistemi oluşturalım. Farklı uygulamalar gerektiren bildirimler için bir arayüz, tüm bildirim türlerinde aynı olması gereken ortak günlük kaydı davranışı için ise bir mixin oluşturacaksın.
Kodunu üç dosyada düzenleyeceksin:
notifiable.dart: Arayüz görevi gören soyut birNotifiablesınıfı tanımla. İki soyut yöntem bildirmelidir:send(String message)ve birgetChannel()döndürenString. Farklı bildirim türleri, kendi kanallarına göre bu yöntemleri farklı şekilde uygulayacaktır.logging.dart: Tüm bildirimlerin sahip olması gereken ortak davranışı sağlayan birLoggingmixin'i oluştur.logSent(String channel, String message)yazdıran[LOG] Sent via [channel]: [message]yöntemini velogTimestamp()yazdıran[LOG] Timestamp recordedyöntemini ekle. Bu davranış tüm bildirim türleri için aynı olduğundan mixin kullanımı için idealdir.main.dart: Her iki dosyayı içe aktar ve arayüzü mixin ile birleştiren iki bildirim sınıfı oluştur:EmailNotificationmixin'ini kullanan veLoggingarayüzünü uygulayan birNotifiablesınıfı.getChannel()yöntemi'Email'döndürmeli vesend()yöntemiSending email: [message]yazdırmalı, ardından kanal ve mesajla birliktelogSent()yöntemini, sonra dalogTimestamp()yöntemini çağırmalıdır.SMSNotificationmixin'ini kullanan veLoggingarayüzünü uygulayan birNotifiablesınıfı.getChannel()yöntemi'SMS'döndürmeli vesend()yöntemiSending SMS: [message]yazdırmalı, ardından kanal ve mesajla birliktelogSent()yöntemini, sonra dalogTimestamp()yöntemini çağırmalıdır.
EmailNotificationoluştur vesend('Hello World')çağrısını yap, boş bir satır yazdır, birSMSNotificationoluştur vesend('Quick update')çağrısını yap
Arayüzün her sınıfı kendi send() ve getChannel() uygulamalarını (farklı davranış) yazmaya zorladığına, mixin'in ise her ikisi için aynı şekilde çalışan günlük kaydı yöntemlerini (ortak davranış) sağladığına dikkat et.
Beklenen çıktı:
Sending email: Hello World
[LOG] Sent via Email: Hello World
[LOG] Timestamp recorded
Sending SMS: Quick update
[LOG] Sent via SMS: Quick update
[LOG] Timestamp recordedKendin dene
import 'notifiable.dart';
import 'logging.dart';
// TODO: Şu özelliklere sahip EmailNotification sınıfını oluşturun:
// - Logging mixin'ini kullanır (with)
// - Notifiable arayüzünü uygular (implements)
// - getChannel() 'Email' değerini döndürür
// - send() 'Sending email: [message]' yazdırır, ardından logSent() ve logTimestamp() fonksiyonlarını çağırır
// TODO: Şu özelliklere sahip SMSNotification sınıfını oluşturun:
// - Logging mixin'ini kullanır (with)
// - Notifiable arayüzünü uygular (implements)
// - getChannel() 'SMS' değerini döndürür
// - send() 'Sending SMS: [message]' yazdırır, ardından logSent() ve logTimestamp() fonksiyonlarını çağırır
void main() {
// TODO: Bir EmailNotification oluşturun ve send('Hello World') fonksiyonunu çağırın
// TODO: Boş bir satır yazdırın
// TODO: Bir SMSNotification oluşturun ve send('Quick update') fonksiyonunu çağırın
}
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
1Nesne Tabanlı Programlamanın Temelleri
Harici DosyalarKütüphaneler ve İçe AktarmalarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar SözcüğüMetotlarÖrnek DeğişkenleriYapıcıların TemelleriTekrar - Basit Hesap Makinesi4Null Güvenliği
Null Güvenliğine GirişNullable ve Non-Nullable? ve ! OperatörleriLate Anahtar Sözcüğü ve Null GüvenliğiNull-Aware OperatörlerSınıflarda Null GüvenliğiTekrar - Kullanıcı Profili Sistemi7Soyut Sınıflar ve Arayüzler
Soyut SınıflarSoyut MetotlarDart'ta ArayüzlerÖrtük ArayüzlerUygulamak ve GenişletmekBirden Çok ArayüzTekrar - Şekil Hesaplayıcı10Koleksiyonlar ve Generics
List, Set, Map Genel BakışTür Güvenli KoleksiyonlarGeneric SınıflarGeneric MetotlarGeneric KısıtlamalarIterable ve IteratorTekrar - Generic Depolama2Dart'ta Yapıcılar
Varsayılan YapıcıAdlandırılmış YapıcılarBaşlatıcı ListeleriSabit YapıcılarFabrika YapıcılarıYönlendiren YapıcılarÖzet - Şekil Oluşturucu5Kapsülleme
Public ve Private Üyeler_ Ön Ek KuralıKütüphane Düzeyinde GizlilikGetter ve Setter DerinliğiBilgi GizlemeTekrar - Öğrenci Kayıtları8Mixin'ler
Mixin'lere GirişMixin OluşturmaBirden Çok Mixin KullanımıMixin'lerde on Anahtar SözcüğüMixin ve Kalıtım KarşılaştırmasıMixin ve Arayüz KarşılaştırmasıÖzet - Hayvan Sistemi11Özel Metotlar
toString() Geçersiz KılmahashCode & == Geçersiz KılmaComparable Arayüzücall() MetodunoSuchMethod Geçersiz KılmaÖzet - Özel Koleksiyon14Tasarım Desenleri Bölüm 1
Tasarım Desenlerine GirişSingleton DeseniFactory DeseniObserver DeseniStrategy Deseni3Sınıf Özellikleri
Örnek ve Static ÜyelerFinal ve Const AlanlarLate DeğişkenlerStatic Metotlar ve AlanlarGetter ve Setter'larÖzet - Banka Hesabı Yöneticisi6Kalıtım
Temel Kalıtımsuper Anahtar SözcüğüMetot Geçersiz Kılma@override Açıklamasıfinal Sınıf Anahtar SözcüğüKurucular ve KalıtımÖzet - Çalışan Hiyerarşisi9Çok Biçimlilik
Çok Biçimlilik TemelleriArayüzler Yoluyla Çok BiçimlilikÇalışma Zamanı Tür Denetimiis ve as OperatörleriCovariant Anahtar KelimesiTekrar - Ödeme İşlemcisi12Asenkron OOP
Future'ler ve async/awaitStream TemelleriStream DenetleyicileriAsenkron YapıcılarSınıf Metotlarında AsenkronlukÖzet - Veri Getirici15Tasarım Desenleri Bölüm 2
Komut DeseniAdaptör DeseniDekoratör DeseniŞablon Metot DeseniDurum DeseniBileşik DesenDepo DeseniKendi başına pratik yap: Online Dart derleyicisi