Java'da ek açıklamaları genişletmek neden mümkün değil?


227

Java ek açıklamalarında neden sadece Java sınıfları gibi kalıtım olmadığını anlamıyorum. Çok faydalı olacağını düşünüyorum.

Örneğin: Belirli bir ek açıklamanın doğrulayıcı olup olmadığını bilmek istiyorum. Miras ile, bu ek açıklamanın a ValidatorAnnotation. Aksi takdirde, bunu nasıl başarabilirim?

Peki, kimse bana bu tasarım kararı için bir neden verebilir mi?


2
BTW, tüm açıklamaların genişlediğine dikkat edin java.lang.annotation.Annotation, yani bu açıklama instanceofaçıkça bildirilmemesine rağmen herhangi bir açıklamadır .
Tomáš Záluský

Yanıtlar:


166

Neden bu şekilde tasarlanmadığı hakkında, cevabı JSR 175 Tasarım SSS bölümünde bulabilirsiniz :

Ek açıklama alt türünü neden desteklemiyorsunuz (bir ek açıklama türü diğerini genişletiyorsa)?

Ek açıklama türü sistemini karmaşıklaştırır ve “Özel Araçlar” yazmayı çok daha zorlaştırır.

...

“Özel Araçlar” - Bilinen ek açıklama türlerini rasgele harici programlar olarak sorgulayan programlar. Örneğin saplama üreteçleri bu kategoriye girer. Bu programlar ek açıklamalı sınıfları sanal makineye yüklemeden okuyacak, ancak ek açıklama arayüzlerini yükleyecektir.

Evet, sanırım bunun nedeni sadece ÖPÜCÜK. Her neyse, bu sorun (diğerleri ile birlikte) JSR 308'in bir parçası olarak ele alınıyor ve hatta Mathias Ricken tarafından geliştirilen bu işlevselliğe sahip alternatif bir derleyici bile bulabilirsiniz .


67
Belki de aptalım ama bence bu sadece basit tutmak için ek açıklamaları uzatamaz. En azından, Java tasarımcıları sınıf mirası hakkında aynı şeyi düşünmüyordu: P
sinuhepop

2
Java 8 M7, alt sınıflandırma ek açıklamalarını desteklemiyor gibi görünüyor. Ne yazık.
Ceki

2
@assylias JEP 104 ek açıklamaları alt sınıflara ayırmakla ilgili değildir. JEP 104, Java 8'de uygulanmıştır, ancak ek açıklamaları alt sınıflara ayırmak hala mümkün değildir (bir ek açıklamanın başka bir ek açıklamayı genişletmesini sağlayın).
Jesper

71

Genişletilebilir ek açıklamalar, başka bir tür sistemi belirtme ve bakımını yapma yükünü etkili bir şekilde artıracaktır. Ve bu oldukça benzersiz bir tip sistemi olurdu, bu yüzden sadece OO tipi bir paradigma uygulayamazsınız.

Bir ek açıklamaya polimorfizm ve kalıtım eklediğinizde tüm sorunları düşünün (örn. Alt ek açıklama tutma gibi meta ek açıklama özelliklerini değiştirdiğinde ne olur?)

Ve tüm bunlar hangi kullanım durumu için karmaşıklık ekledi?

Belirli bir ek açıklamanın bir kategoriye ait olup olmadığını bilmek ister misiniz?

Bunu dene:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

Gördüğünüz gibi, sağlanan olanakları kullanarak ek açıklamaları gereksiz acı olmadan kolayca gruplayabilir ve kategorilere ayırabilirsiniz.

Bu nedenle, KISS , Java diline bir meta-tip yazı sistemi getirmemenin nedenidir.

[ps değiştir]

String'i sadece gösteri için ve açık uçlu bir meta ek açıklama için kullandım. Kendi verilen projeniz için açık bir şekilde kategori türlerini sıralayabilir ve belirli bir ek açıklamaya birden çok kategori ("çoklu kalıtım") belirtebilirsiniz. Değerlerin tamamen sahte olduğunu ve yalnızca tanıtım amaçlı olduğunu unutmayın:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}


Çalışmıyor yanlış yazdırılacak:@Target(ElementType.ANNOTATION_TYPE) @Retention(RetentionPolicy.RUNTIME) @interface C {}; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @C public @interface F {} class a{ @F public void S() {} } @Test public void blahTest() throws NoSuchMethodException { Method m = a.class.getMethod("S"); System.out.println(m.isAnnotationPresent(C.class)); }
user1615664

Bir ek açıklama ekliyoruz. a # S'nin F ek açıklaması vardır. F'nin kendisi C tarafından ek açıklanır.
alphazero

Evet doğru. Ancak, Ek Açıklama proxy'sini okumak yerine bunu daha temiz bir şekilde yapmanın bir yolu var mı?
user1615664

12

Bir anlamda Ek Açıklamalar - meta Ek Açıklamalar ile zaten var. Bir ek açıklamayı meta bilgilerle eklerseniz, bu birçok yönden ek bir arayüz genişletmeye eşdeğerdir. Ek açıklamalar arabirimlerdir, bu nedenle polimorfizm gerçekte devreye girmez ve doğada statik oldukları için çalışma zamanı dinamik gönderimi olamaz.

Doğrulayıcı örneğinizde, yalnızca ek açıklamada ek açıklama türünü alabilir ve bir doğrulayıcı meta ek açıklaması olup olmadığını görebilirsiniz.

Kalıtımın yardımcı olacağını görebildiğim tek kullanım durumu, ek açıklamayı süper türe göre almak istiyorsanız, ancak bu bir karmaşıklık katacaktır, çünkü belirli bir yöntem veya tür üzerinde iki ek açıklama olabilir, başka bir deyişle, yalnızca tek bir nesne yerine bir dizinin döndürülmesi gerekir.

Bu yüzden nihai cevabın kullanım durumlarının ezoterik olduğunu ve buna değmeyecek şekilde daha standart kullanım durumlarını zorlaştırdığını düşünüyorum.


5

Java ek açıklama desteği tasarımcıları, Java topluluğunun zararına bir dizi "basitleştirme" yaptı.

  1. Hiçbir ek açıklama alt türü, birçok karmaşık ek açıklamayı gereksiz yere çirkin hale getirmez. Ek açıklamalarda üç şeyden birini tutabilecek bir özellik olamaz. Kişinin geliştiricileri karıştırdığı ve üçünden yalnızca birinin kullanıldığından emin olmak için çalışma zamanı doğrulaması gerektiren üç ayrı özelliğe sahip olması gerekir.

  2. Site başına belirli bir türde yalnızca bir ek açıklama. Bu, tamamen gereksiz tahsilat açıklama modeline yol açmıştır. @Validation ve @Validations, @Image ve @Images, vb.

İkincisi Java 8'de düzeltiliyor, ancak çok geç. Java 5'te nelerin mümkün olduğuna bağlı olarak birçok çerçeve yazılmıştır ve şimdi bu API siğilleri uzun süre kalmak için buradadır.


1
Sadece bu da değil, XML şeması tarafından desteklenen özyinelemeli iç içe özniteliklere sahip özellikleri tanımlamak da imkansız hale gelir. Bu, ek açıklamaları XML'den kesinlikle daha az güçlü hale getirir
user2833557

3

Bu soruya cevap vermem için üç yıl geç kalmış olabilirim, ama ilginç buldum çünkü kendimi aynı yerde buldum. İşte benim almam. Ek açıklamaları Numaralandırma olarak görüntüleyebilirsiniz. Tek yönlü bir bilgi sağlarlar - kullanırlar ya da kaybederler.

Bir web uygulamasında GET, POST, PUT ve DELETE simüle etmek istediğim bir durum vardı. Çok kötü "HTTP_METHOD" olarak adlandırılan bir "süper" ek açıklama istedim. Daha sonra fark etmedi benim için şafak vakti. Eh, DELETE ve PUT tanımlamak için HTML formunda gizli bir alan kullanarak yerleşmek zorunda kaldı (çünkü POST ve GET zaten kullanılabilir).

Sunucu tarafında, "_method" adında gizli bir istek parametresi aradım. Değer PUT veya DELETE ise, ilişkili HTTP istek yöntemini geçersiz kılar. Bunu söyledikten sonra, işi yapmak için bir ek açıklama uzatmam gerekip gerekmediği önemli değildi. Tüm ek açıklamalar aynı görünüyordu, ancak sunucu tarafında farklı muamele gördüler.

Bu durumda, ek açıklamaları genişletmek için kaşıntıyı bırakın. Onlara 'işaretçi' muamelesi yapın. Bazı bilgileri "temsil eder" ve bazı bilgileri "manipüle etmeleri" gerekmez.


2

Düşünebileceğim bir şey, birden fazla ek açıklama alma olasılığıdır. Böylece aynı yere doğrulayıcı ve daha spesifik bir ek açıklama ekleyebilirsiniz. Ama yanılmış olabilirim :)


2

Bunu hiç düşünmedim ama ... haklı görünüyorsun, ek açıklamaların miras tesisiyle ilgili bir sorun yok (en azından bununla ilgili sorunu görmüyorum).

'Doğrulayıcı' ek açıklama içeren örneğiniz hakkında - o zaman 'meta ek açıklama' yaklaşımından yararlanabilirsiniz . Yani, tüm ek açıklama arayüzüne meta ek açıklama uygularsınız.


Bu soruya cevap vermem için üç yıl geç kalmış olabilirim, ama ilginç buldum çünkü kendimi aynı yerde buldum.
mainas

1

aynı problemim var. Hayır, yapamazsınız. Bazı standartlara uymak için ek açıklamalarda özellikler yazmak için kendimi 'disiplinli' yaptım, bu yüzden ek açıklama aldığınızda dışarıda sahip olduğu özelliklerle ne tür bir ek açıklama olduğunu 'koklayabilirsiniz'.

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.