Java örneğinin yerine geçecek mi?


10

Bu yüzden gerçek dünyada (akademik projelerin dışında) programlama konusunda oldukça yeniyim ve instanceofbelirli bir nesnenin hangi sınıf olduğunu belirlemek için kullanmanın kötü bir şey olduğunu söyleyen birçok gönderiyle karşılaştım .

Benim durumum üç sınıfım, bir temel ürün sınıfı, biri bunu genişleten diğeri ise onu genişletiyor. Bunlar bir veritabanında aynı tabloda depolanır ve ben onları çekmek için her yöntemleri kullanmak için gereken bazı kod var.

Bunu yapmanın en iyi yolu nedir? Polimorfizm hakkında bazı şeyler okudum ama yaşadığım sorunu gideren örnekler bulamıyorum. Hepsi genellikle farklı nesnelerden farklı şeyler çekmem gerektiğinden benim için çalışmayacak bir yöntemi geçersiz kılar.

Bunu yapmanın daha iyi bir yolu var mı ya instanceofda nesnelere özgü alanları elde etmek için kullanma ya da bir tür yansıma ile sıkışmış mıyım?


10
Anahtar kelimenin instanceofyanlış olması değil; bir nesnenin sınıfını bulmaya çalışmak genellikle problemdir. Her zaman yanlış değil, ama muhtemelen sizin durumunuzda. Belki bize ne yapmaya çalıştığınızı söylerseniz, polimorfizm kullanarak bir çözüm önerebiliriz.
Andres F.

2
Tamam, her sınıfın kendine özgü verileri vardır. Bunlardan belirli verileri almak istiyorum. Sanırım cevabı yaşadığım yardımla gerçekleştirdim. getSpecifics()Her biri sınıfa özgü veriler döndüren her biri için farklı bir şekilde uygulanan bir yöntem gibi bir şey mi?
Thomas Mitchell

Yanıtlar:


16

instanceofCesaret kırılmasının nedeni OOP olmamasıdır.

Bir nesnenin arayanının / kullanıcısının hangi somut sınıf olduğunu, değişkenin hangi türden farklı olarak bildirildiğini bilmesi için hiçbir neden olmamalıdır.

Alt sınıflarda farklı davranışlara ihtiyacınız varsa bir yöntem ekleyin ve bunları farklı şekilde uygulayın.


1
Yani getSpecifics()her sınıf için her sınıfın özelliklerini döndürecek bir yöntem (ya da benzer bir şey) Bu en iyi yaklaşım mı?
Thomas Mitchell

@Schmooo Sınıf ağacında ortak işlevselliklerin nerede olduğunu ve her düzeyde hangi sözleşmelerin var olduğunu düşünmeniz gerekir.

3
Peki ya nesneniz katmanları aştığında ve tür bilgisi kaybolduğunda ne olur? Örnek a List. Bunu alan bir nesneye geçiriyorum Iterable. Şimdi bu ikinci nesne onu Listoptimizasyon için a alan veya Iterableçok daha yavaş olan üçüncü bir nesneye geçirir. İkincisi bunun bir liste olduğunu bilmemeli, ama üçüncüsü bilmek istiyor. Üçüncü nesne, optimizasyonun uygulanıp uygulanamayacağını görmek için instanceof öğesini kontrol etmemeli mi? Örneğin FluentIterable, bunu yapan guava'ya bakın .
Laurent Bourgault-Roy

1
Sınıfa yöntemi eklemek zorunda olduğunuz her zaman böyle olmadığını söyleyebilirim. Örneğin, bazı kodlar bir istisna alır ve türüne bağlı olarak onunla bir şeyler yapması beklenir. Söyleyin, bir rapor hazırlayın veya hatadan kurtarmak için bir şeyler yapın. Bu tür işlevsellik kesinlikle istisnalara uymuyor. Veya, sınıflar bir dış kütüphaneden geliyorsa, bu sınıfları değiştirmek için bile araçlarınız yoktur. Bu durumda, güvenmek kesinlikle geçerli olduğunu düşünüyorum instanceof.
Malcolm

9

instanceof ille de kötü bir şey değildir, ancak kişinin bakması gereken bir şeydir.

Düzgün çalıştığı yere bir örnek, taban türünün bir koleksiyonunu aldığı ve yalnızca bir alt türün olanlarını istediğiniz bir yerdir. Ağ adreslerini almak NetworkInterface.getNetworkInterfaces(), bazıları Inet4Address ve bazıları Inet6Address olan InetAddress nesneleri koleksiyonuna sahip NetworkInterface nesnelerini döndürür. Biri koleksiyonu Inet4Address nesneleri için filtrelemek istiyorsa, instanceof öğesini kullanmak gerekir.

Orijinal yayında anlatılan durumda, bir Base sınıfı, bu temel sınıfı genişleten ve genişletilmiş sınıfı genişleten bir şey vardır. Tamamen bilgilendirici olmasa da, bunun ideal tasarımdan daha az temelleri olduğu görülüyor.

Bu şekilde tasarlanması için iyi bir neden yoksa (daha önceki bir sürümün özellikleri arasında geriye dönük uyumluluk) bir temel sınıfı döndürürken, temel türlere göz atmaya çalışmamalısınız. Size bir Set döndürülürse, bir set aldığınızı bilirsiniz. Geliştiricinin daha sonra belirli bir türü (SortedSet) döndürmek veya temel türü (HashSet'ten TreeSet'e) değiştirmek için fikrini değiştirmesine izin verir.

Nesnelerin, farklı bir tür ayrımı gerektirmeyen daha iyi bir sınıf modeli yapıp yapamayacağını görmek için nasıl yapılandırıldığını ve ebeveynleştirildiğini düşünün.


Arabirimin bir isOfType(SomeEnum.IPv4)yöntem belirtmesi , bu tür nitelikleri filtrelemenin, somut türü incelemek yerine daha iyi bir yol olabilmesi mümkündür instanceof. IPv4 uygulama sınıfınızı daha sonra bölmek isterseniz ne olur? Bu her zaman daha iyi değil, ama bir düşüncedir.
Steven Schlansker

@StevenSchlansker Bu belirli bir sınıf için işe yarayabilir. Peki ya bir dökümün mümkün olup olmadığını görmek için beton tipini incelemek gerekiyorsa (ya da sadece istisna atıp istisna eder mi?) Inet6Address, InetAddress'ten daha fazla yöntem uygular. Arayüzlerle (paketteki her sınıfı? Ya da sınıf yükleyicisini? Numaralandıran bir numaralandırma) çalışmak ve yöntemin elle uygulanması (ya da Object içindeki bazı yansıma kodları) anlamına gelmesi zor olurdu. Nasıl yapılacağını düşünün (o instanceof Serializable) || (o instanceof Externalizable). instanceof alternatif daha iyidir

1

GetClass () yöntemini kullanabilirsiniz.

Üç farklı sınıfa ihtiyacınız olduğundan emin misiniz? Belki içinde bir anahtar bulunan bir sınıf daha iyi hizmet eder?


7
getClassve instanceofdezavantajları paylaşın. Polimorfizm her ikisinden de daha iyidir ve OP'nin kullanım durumuna uymadığını görmüyorum.

İlk cümlene karşı hiçbir şeyim yok. Ama ikincisi - üzgünüm, ne demek istediğini anlamıyorum.
Gangnus

1
İle getClasshala aynı sorunu paylaşmıyorum instanceof? Hala neye sahip olduğumu bulmam ve daha sonra bir dizi fonksiyon çağırmam gerekecek. İdeal olarak ben o nesneye döküm gerek kalmadan o sınıfa özgü verileri döndüren bir yöntem istiyorum.
Thomas Mitchell

Çoğunlukla daha iyi bir seçim olduğu için Polimorfizmi görmezden geldiğinizden şikayet ediyorum. Eminim ki sorudaki kullanım durumu polimorfizm ile yapılabilir, bu yüzden de kullanma gereğini görmüyorum. (Bunun dışında, sadece bir başkasının cevabını tekrarlamak hoş değil.)

2
@Gangus Bunu bir "saldırı" olarak düşünmüyorum, demek istediğim suç değil. Fakat herneyse. Hayır, soru "başka ne kullanılabilir" değil, "bunu yapmanın daha iyi bir yolu var mı?" Tartışmak istemediğiniz sürece bunu yapmak için getClassdaha iyi bir yol yoktur, cevabın çoğunu alan hiçbir iş yoktur ;-)

1

Genellikle kendimi bir şeyin türünü bilmek isterken bulduğumda, nesne yapımı yanlış uyguladım. Bu zamanların çoğu LSP'yi ihlal etmeye geliyor .

Ancak dinamik dağıtım yapmanın ve bir ton kazan plakası kodunu kaydetmem ve nesne yapımın geleceğine karşı korumamın bir yolu olmasını istediğim zamanlar var. C #, çerçevenin daha yeni bölümlerinde dinamik anahtar sözcüğü sağlar, ancak bildiğim kadarıyla Java'nın hala benzer bir şeyi yoktur.

Bununla birlikte, instanceof, kalıtsallığı düzgün bir şekilde destekleyeceği için sınıfları karşılaştırmaktan genellikle daha iyidir. Yansıtma API'sından isAssignableFrom ve diğerleri gibi yöntemleri de kullanabilirsiniz. Dinamik dağıtım gibi bir şey uygulamak istiyorsanız, yansıma API'si aracılığıyla yapılabilir, ancak dikkatli olun, yavaş olacaktır. Dikkatli kullanın, ideal olarak uygulamanızın nesne yapısını ve tasarımını düzeltmelisiniz.

Bu yardımcı olur umarım

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.