Tasarım: Üst sınıfa geri arama


13

Bir nesneyi çocuklarla modellerken, çocukları ana sınıfın bir üyesi olarak kompozisyon yoluyla dahil etmek yaygındır. Bazen çocukların ebeveyne bir şey söylemeleri gerekir, ebeveynlerinin bir işlevini çağırmaları gerekir. Bu nasıl C ++ kullanarak yapılabilir? Bazı seçenekler:

  1. Üst sınıfı global yapın, bu nedenle alt nesneler üst nesnenin üye işlevlerini çağırabilir.

  2. Üst nesneyi her alt nesneye bir işaretçi veya başvuru olarak enjekte edin. Daha sonra çocuğun üst nesneye bir şey söylemesi gerektiğinde bunu yapabilir, çünkü kullanabileceği bir üye değişkeni vardır.

Bunu yapmanın diğer yöntemleri nelerdir? Bu tür bir şey için genel bir tasarım deseni veya adı var mı?

Ayrıntılar diğer nesne yönelimli dillerde farklı olacak çünkü C + + fikirler ve çözümler ilgileniyorum unutmayın. Örneğin yukarıdaki 2. maddede 'işaretçilerden veya referanslardan' bahsedilmektedir ve her ikisi de sadece C ++ ile mümkündür. C ++ diğer dillerde bulunmayan dil özelliklerine sahiptir, bu nedenle soruna bir çözümün uygulanması potansiyel olarak bu dil özelliklerini içerecek ve çözümü başka bir dilde ortaya çıkabileceklerden farklı kılacaktır.


bir örnek ekleyebilir misin Bu sorunuz için geçerli bir örnek mi? Sipariş öğelerine (alt öğe) sahip bir orderobject (= üst öğe) var ve sipariş öğesi miktarı değiştirildiğinde sipariş toplamını güncellemek mi istiyorsunuz? Yoksa tamamen farklı bir şey mi düşünüyorsunuz?
k3b

@ k3b Evet, bu geçerli bir örnek. Çocukta bazı bilgiler değişti, ebeveynin bir şey yapmasını gerektirdi.
sashang

her bir alt sınıfa bazı kurucu parametreleri ve referans veri üyeleri eklemeniz yeterlidir.
tp1

Çocuğun ebeveyn hakkında her şeyi bilmesi gerekiyor mu, yoksa bir basit delegateyeterli mi?
Julien Guertault

Yanıtlar:


16

İlk olarak, bu bir kod kokusu olabilir. Ebeveyn / çocuk için kompozisyon kullanmanın amacı, ebeveynin çocukları tanımasıdır, bunun tersi de değildir. Özellikle ilişki bir 'içerdiğinden' daha fazla ise 'oluşur'.

Üst öğeye başvuru mümkündür ve C ++ 'da oldukça yaygındır. Diğer dillerde, bir fonksiyon nesnesi veya olayı, çocuğun yabancıların bilmek isteyebileceği şeyleri iletmesine izin vermek için daha sık kullanılır. Bu yaygın bir yayıncı-abone çeşidi çeşididir. Ben daha deyimsel olan hangi C ++ sürümü kullandığınız ve kod temeli standartlarına bağlı olduğundan şüpheleniyorum.


Benim durumumda bu bir kod kokusu. Mükemmel cevap.
Martin Pfeffer

3

Diğerlerinin işaret ettiği gibi, ana nesneyi bir işaretçi veya referans olarak enjekte etme temel fikri prensip olarak gitmenin yoludur.

Bunun bir dezavantajı vardır: ebeveyn ve çocuk arasında döngüsel bir bağımlılık elde edersiniz. Bundan kaçınmak istiyorsanız IParent, ebeveyninizin miras aldığı soyut bir temel sınıf (arayüz) tanımlayın . IParentyöntemleri çocuğun çağırmak istediği sanal işlevler olarak içermelidir. Ardından, ebeveyne referans olarak enjekte edin IParent. Bu, birim testini çocuğu çok daha kolay hale getirir, çünkü artık üst nesneyi sahte bir nesne ile kolayca değiştirebilirsiniz.

Çocuğunuzun ana nesnenizin yalnızca bir işlevini çağırması gerekiyorsa, IParentsınıfın tamamı büyük olabilir. Bu durumda, üye işlevine alt öğeye bir işaretçi veya bu üye işlevini kapsayan bir işlev nesnesi enjekte etmek yeterli olacaktır.


2

Yapabileceğiniz şey, kompozisyona göre alt sınıftaki ebeveyne bir referans tutmaktır. Bu şekilde, çocuk ebeveynini tanır ve üzerinde genel yöntemler çağırabilir.

Öyleyse seçenek 2 ile giderdim. Bununla birlikte, bir çocuk ebeveyninden çıkarıldığında, çocuktaki ebeveyne olan referansı kaldırmanız ve bunu null değerine (veya varsa yeni bir ebeveyne) yönlendirmeniz gerekir. bir). Veya bağlama bağlı olarak alt nesneyi silebilirsiniz.


1

Ebeveyne bir başvuru veya işaretçi iletin. Onları ebeveynin arkadaşları yapabilir veya çağrılan yöntemi herkese açık yapabilirsiniz. Yukarıdakilerden herhangi birini yapmak istemiyorsanız, onlara ebeveynin yöntemlerinden birini herkese açık olarak gösteren ve kendisinin ebeveynin iç içe geçmiş bir sınıfı olan bir "köprü" nesnesi iletebilirsiniz (bu nedenle her ebeveyn yöntemine erişimi vardır) ). Ancak bu birçok durumda biraz fazla karmaşık olabilir.


1

2) Üst nesneyi her alt nesneye bir, işaretçi veya başvuru olarak enjekte edin. Daha sonra çocuğun üst nesneye bir şey söylemesi gerektiğinde bunu yapabilir, çünkü kullanabileceği bir üye değişkeni vardır.

Mükemmel uygulanabilir bir seçenektir. Tüm modern diller, başka bir dile atıfta bulunmak için kullanılabilecek bir özelliğe sahiptir.


1

Hafif bir varyasyon ile benzer bir yaklaşım vardır, ancak bu avantajlar sağlar:

Ebeveyn A'nın Bileşen C içerdiğini varsayalım.

Bileşen C'de, InterfaceC'yi bildirin ve referansı tutun. Bu, bileşenin dış dünya ile olan arabirimidir.

Üst A, InterfaceC'yi uygular ve başvurusunu Bileşen C'ye ayarlar. Bileşen C, A Bileşeni'ni InterfaceC olarak görür.

Fikir şu: Bir bileşen, arayüzünü kullanarak dışarıdan konuşuyor.

Bunu ebeveynin doğrudan ayarlanması üzerinde kullanmanın avantajları:

Bileşenin bir şey yaptığını ve üst öğeye bildirmesi gerektiğini söyleyin. Arayüzü çağırır. Daha sonra, ebeveyni değiştirmek istediğinize karar verirsiniz. Bileşen hiç umursamıyor ve üzerinde herhangi bir değişiklik yapmayacaksınız.

Daha sonra bir etkinliğin birçok nesnesini bilgilendirmek istediğinizi söyleyin. Sadece bir InterfaceC listesi oluşturun ve bu listeye referanslar ekleyin.

Dezavantajları: Bir ebeveyn sınıfı birçok arabirimi uygulamaya sokacaktır (bunun bir avantaj olduğunu düşünüyorum, çünkü sınıf beyanına bakarak, kiminle konuştuğunu hemen biliyorum)


0

Bunun c # 'a özel olduğunu unutmayın. C ++ benzer bir şey olup olmadığını bilmiyorum.

Butonlu bir gui-formunuz varsa , Observer_pattern veya Publish – abone olma modeli olarak da bilinen Event-Subscribtion'ı kullanarak farklı bir yaklaşımınız olur .

Buton genellikle nerede yaşadığı belirli bir formu bilmez. Bunun yerine düğme bir olayı tetikler veya yayınlar ve form abone olunan bir bildirim alır ve buna göre tepki verebilir.

GUI-ler dışında bu mekanizma her ebeveyn-çocuk ilişkisinde kullanılabilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.