Bir arayüz içinde bir iç sınıf oluşturmak mümkün müdür ?
Mümkünse, herhangi bir arayüz nesnesi oluşturmayacağımız için neden böyle bir iç sınıf yaratmak isteyelim?
Bu iç sınıflar herhangi bir geliştirme sürecinde yardımcı oluyor mu?
Yanıtlar:
Evet, yapabilirsiniz iç içe geçmiş bir sınıf veya bir Java arayüzünden (aksine kanının bir "diye bir şey yoktur notu içindeki bir iç sınıfı oluşturmak, hem de statik iç sınıf ' 'iç' ve hiçbir şey yok, bu tamamen mantıksız:' outter "sınıfı, yuvalanmış bir sınıf statik olduğunda, bu nedenle" statik iç "olamaz).
Her neyse, aşağıdaki iyi derler:
public interface A {
class B {
}
}
Arayüz tanımına doğrudan bir tür "sözleşme denetleyicisi" koyduğunu gördüm (iyi, arayüzde yuvalanmış sınıfta, statik yöntemlere sahip olabilir, arayüzün kendisinin aksine, olamaz). Doğru hatırlıyorsam böyle görünüyorum.
public interface A {
static class B {
public static boolean verifyState( A a ) {
return (true if object implementing class A looks to be in a valid state)
}
}
}
Böyle bir şeyin yararlılığı hakkında yorum yapmadığıma dikkat edin, sadece sorunuzu yanıtlıyorum: yapılabilir ve bu, ondan yapıldığını gördüğüm türden bir kullanımdır.
Şimdi böyle bir yapının yararlılığı üzerine yorum yapmayacağım ve şunu gördüm: Onu gördüm, ama çok yaygın bir yapı değil.
Burada 200KLOC kod tabanı, bunun tam olarak sıfır zamanda gerçekleştiği yerde (ama daha sonra, diğer insanların tamamen normal bulacağı şekilde tam olarak sıfır zamanda gerçekleşen kötü uygulamaları düşündüğümüz birçok başka şey de var ...
interface
s yapabilirsiniz değil iç sınıfları var. İç içe geçmiş bir sınıfın static
değiştiricisini atlayabilirsiniz, interface
ancak yine de bu bir iç sınıf değil, iç içe geçmiş bir sınıftır.
B
sınıf statik bir iç içe geçmiş sınıftır ve iç sınıf değildir; arayüzler özel muamele görür. Spesifikasyonun kendisi haricinde çevrimiçi olarak bundan bahsedemedim: "Bir arayüzün üye sınıfı dolaylı olarak statiktir, bu nedenle asla bir iç sınıf olarak kabul edilmez." docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Evet, arayüzlerin içinde sınıflarımız olabilir. Bir kullanım örneği olabilir
public interface Input
{
public static class KeyEvent {
public static final int KEY_DOWN = 0;
public static final int KEY_UP = 1;
public int type;
public int keyCode;
public char keyChar;
}
public static class TouchEvent {
public static final int TOUCH_DOWN = 0;
public static final int TOUCH_UP = 1;
public static final int TOUCH_DRAGGED = 2;
public int type;
public int x, y;
public int pointer;
}
public boolean isKeyPressed(int keyCode);
public boolean isTouchDown(int pointer);
public int getTouchX(int pointer);
public int getTouchY(int pointer);
public float getAccelX();
public float getAccelY();
public float getAccelZ();
public List<KeyEvent> getKeyEvents();
public List<TouchEvent> getTouchEvents();
}
Burada kod, daha sonra getKeyEvents () gibi yöntem tanımlarında kullanılan olay nesneleri hakkındaki bilgileri kapsüllemek için iki iç içe geçmiş sınıfa sahiptir. Bunları Giriş arayüzünde bulundurmak, uyumu geliştirir.
Geçerli bir kullanım olan IMHO, çevreleyen arayüz yöntemleri tarafından alınan veya döndürülen nesneleri tanımlamaktır. Tipik olarak veri tutma yapıları. Bu şekilde, nesne sadece o arayüz için kullanılıyorsa, daha uyumlu bir şekilde her şeye sahip olursunuz.
Örnek olarak:
interface UserChecker {
Ticket validateUser(Credentials credentials);
class Credentials {
// user and password
}
class Ticket {
// some obscure implementation
}
}
Ama her neyse ... bu sadece bir zevk meselesi.
Java 7 spesifikasyonundan alıntı :
Arayüzler üye türü bildirimleri içerebilir (§8.5).
Bir arabirimdeki üye türü bildirimi örtük olarak statik ve geneldir. Bu değiştiricilerden birini veya her ikisini fazladan belirtmeye izin verilir.
Bir Java arabirimi içinde statik olmayan sınıfları bildirmek mümkün DEĞİL, bu bana mantıklı geliyor.
İlginç bir kullanım örneği, burada açıklandığı gibi bir iç sınıf aracılığıyla arayüz yöntemlerine bir tür varsayılan uygulama sağlamaktır: https://stackoverflow.com/a/3442218/454667 (tek sınıflı kalıtım sorununun üstesinden gelmek için).
Kesinlikle mümkündür ve yararlı bulduğum bir durum, bir arayüzün özel istisnalar atması gerektiği durumdur. İstisnaları, kaynak ağacınızı önemsiz istisna dosyalarının yığınlarıyla doldurmaktan daha temiz olduğunu düşündüğüm ilişkili arayüzleriyle koruyun.
interface MyInterface {
public static class MyInterfaceException extends Exception {
}
void doSomething() throws MyInterfaceException;
}
Evet, bir arabirim içinde statik sınıf tanımlarına sahip olmak mümkündür, ancak bu özelliğin belki de en kullanışlı yönü, enum türlerini (özel tür statik sınıflardır) kullanırken olabilir. Örneğin şuna benzer bir şeye sahip olabilirsiniz:
public interface User {
public enum Role {
ADMIN("administrator"),
EDITOR("editor"),
VANILLA("regular user");
private String description;
private Role(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
public String getName();
public void setName(String name);
public Role getRole();
public void setRole(Role role);
...
}
@Bachi'nin bahsettiği şey, Scala'daki özelliklere benzer ve aslında bir arabirim içinde yuvalanmış bir sınıf kullanılarak uygulanır. Bu, Java'da simüle edilebilir. Ayrıca java özelliklerine veya mixins modeline bakın?
Belki bazı farklı uygulama davranışları gibi daha karmaşık yapılar istediğinizde, şunları göz önünde bulundurun:
public interface A {
public void foo();
public static class B implements A {
@Override
public void foo() {
System.out.println("B foo");
}
}
}
Bu sizin arayüzünüzdür ve uygulayıcı bu olacaktır:
public class C implements A {
@Override
public void foo() {
A.B b = new A.B();
b.foo();
}
public static void main(String[] strings) {
C c = new C();
c.foo();
}
}
Bazı statik uygulamalar sağlayabilir, ancak bu kafa karıştırıcı olmaz, bilmiyorum.
Bu tür bir yapı için bir kullanım buldum.
Gruplanmış tüm sabitlere erişebilirsiniz; sınıfın adı bu durumda bir ad alanı görevi görür.
Şu anda ihtiyacım var. Çeşitli yöntemlerinden benzersiz bir sınıf döndürmenin uygun olacağı bir arayüzüm var. Bu sınıf, yalnızca bu arabirimin yöntemlerinden gelen yanıtlar için bir kap olarak anlamlıdır.
Bu nedenle, yalnızca bu arabirimle ilişkilendirilen statik bir iç içe geçmiş sınıf tanımına sahip olmak uygun olacaktır, çünkü bu arabirim bu sonuçların kapsayıcı sınıfının oluşturulduğu tek yer olmalıdır.
Örneğin Groovy'deki özellikler (uygulanan yöntemlerle smth benzeri arabirim). Tüm yöntemlerin uygulandığı iç sınıfı içeren bir arayüzde derlenirler.