noSuchMethod Override
Coddy'nin Dart Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 74 / 110.
Bir nesne üzerinde var olmayan bir metodu çağırdığınızda, Dart normalde bir NoSuchMethodError hatası fırlatır. Ancak, bu çağrıları yakalamak ve onları uygun bir şekilde işlemek için özel noSuchMethod() metodunu geçersiz kılabilirsiniz.
noSuchMethod() kullanmak için, sınıfınızın ayrıca bir arayüz uygulaması veya dynamic tipleme kullanması gerekir.
Metot, gerçekleştirilmeye çalışılan çağrı hakkında ayrıntılar içeren bir Invocation nesnesi alır:
class Flexible {
@override
dynamic noSuchMethod(Invocation invocation) {
var methodName = invocation.memberName.toString();
print('Called: $methodName');
return null;
}
}
void main() {
dynamic obj = Flexible();
obj.anyMethod(); // Çağrıldı: Symbol("anyMethod")
obj.anotherOne(42); // Çağrıldı: Symbol("anotherOne")
}Invocation nesnesi, çağrı hakkında yararlı bilgiler sağlar - memberName size yöntem adını bir Symbol olarak verir, positionalArguments iletilen argümanları içerir ve isMethod bunun bir getter veya setter yerine bir yöntem çağrısı olup olmadığını size bildirir.
class Logger {
@override
dynamic noSuchMethod(Invocation invocation) {
print('Method: ${invocation.memberName}');
print('Args: ${invocation.positionalArguments}');
return 'handled';
}
}
void main() {
dynamic log = Logger();
var result = log.save('data', 123);
print(result); // işlendi
}Bu teknik, proxy nesneleri, test için mock sınıfları oluşturmak veya rastgele metot çağrılarına yanıt veren esnek API'ler inşa etmek için kullanışlıdır. Ancak, derleme zamanı tür denetimini (compile-time type checking) devre dışı bıraktığı için bu tekniği idareli kullanın.
Görev
KolayBir nesne üzerinde yapılan tüm metot çağrılarını yakalayan ve kaydeden bir metot günlüğü (method logger) oluşturalım! Tanımlanmamış metot çağrıları hakkındaki bilgileri yakalamak ve metot adına göre akıllıca yanıt vermek için noSuchMethod() kullanan bir sınıf oluşturacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
method_logger.dart: Tanımlanmamış metotlara yapılan çağrıları yakalayan birMethodLoggersınıfı oluşturun. Günlüğünüz (logger),noSuchMethod()metodunu şu işlemleri yapacak şekilde geçersiz kılmalıdır (override):- Çağrıdan (invocation) metot adını çıkarın (bu,
Symbol("methodName")gibi bir Symbol olacaktır - bunu bir dizeye dönüştürmeniz ve sadece adı çıkarmanız gerekecektir) - Metot adını ve varsa konumsal argümanları şu formatta yazdırın:
Called: [methodName] with args: [arguments] - Metot adına göre özel bir yanıt döndürün:
- Eğer metot adı
getiçeriyorsa,'data retrieved'dizesini döndürün - Eğer metot adı
saveiçeriyorsa,'data saved'dizesini döndürün - Aksi takdirde,
'unknown action'dizesini döndürün
- Eğer metot adı
- Çağrıdan (invocation) metot adını çıkarın (bu,
main.dart: Günlüğünüzü içe aktarın ve çeşitli tanımlanmamış metot çağrılarını nasıl işlediğini gösterin. Dart'ın var olmayan metotları çağırmaya izin vermesi içindynamictipleme kullanmayı unutmayın:- Dinamik bir değişken kullanarak bir
MethodLoggerörneği oluşturun - Üzerinde
getUserData('Alice', 42)metodunu çağırın ve dönen sonucu yazdırın - Üzerinde
saveRecord('important')metodunu çağırın ve dönen sonucu yazdırın - Üzerinde
processItem()metodunu çağırın (argümansız) ve dönen sonucu yazdırın
- Dinamik bir değişken kullanarak bir
Bir Symbol'den metot adını çıkarmak için, onu bir dizeye dönüştürebilir ve ardından tırnak işaretleri arasındaki adı ayıklayabilirsiniz. Örneğin, Symbol("myMethod").toString() size 'Symbol("myMethod")' sonucunu verir.
Beklenen çıktı:
Called: getUserData with args: [Alice, 42]
data retrieved
Called: saveRecord with args: [important]
data saved
Called: processItem with args: []
unknown actionKopya kağıdı
noSuchMethod() yöntemi, bir nesne üzerinde mevcut olmayan yöntemlere yapılan çağrıları yakalamanıza olanak tanır. Bunu kullanmak için sınıfınızın dynamic yazımını kullanması veya bir arayüz uygulaması gerekir.
Tanımlanmamış yöntem çağrılarını işlemek için noSuchMethod() yöntemini geçersiz kılın (override):
class Flexible {
@override
dynamic noSuchMethod(Invocation invocation) {
var methodName = invocation.memberName.toString();
print('Called: $methodName');
return null;
}
}
void main() {
dynamic obj = Flexible();
obj.anyMethod(); // Called: Symbol("anyMethod")
obj.anotherOne(42); // Called: Symbol("anotherOne")
}Invocation nesnesi, çağrı hakkında bilgi sağlar:
memberName- bir Symbol olarak yöntem adıpositionalArguments- yönteme iletilen argümanlarisMethod- bunun bir getter veya setter yerine bir yöntem çağrısı olup olmadığını belirtir
class Logger {
@override
dynamic noSuchMethod(Invocation invocation) {
print('Method: ${invocation.memberName}');
print('Args: ${invocation.positionalArguments}');
return 'handled';
}
}
void main() {
dynamic log = Logger();
var result = log.save('data', 123);
print(result); // handled
}Bu teknik; proxy nesneleri, test için mock sınıfları veya esnek API'ler oluşturmak için kullanışlıdır, ancak derleme zamanı tür denetimini devre dışı bıraktığı için idareli kullanılmalıdır.
Kendin dene
import 'method_logger.dart';
void main() {
// TODO: dinamik yazım kullanarak bir MethodLogger örneği oluşturun
// dynamic kullanmak, derleme zamanında mevcut olmayan metotların çağrılmasına olanak tanır
dynamic logger;
// TODO: getUserData('Alice', 42) fonksiyonunu çağırın ve sonucu yazdırın
// TODO: saveRecord('important') fonksiyonunu çağırın ve sonucu yazdırın
// TODO: processItem() fonksiyonunu argüman olmadan çağırın ve sonucu yazdı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
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ı