Java'da arayüz değişkenleri neden varsayılan olarak statik ve sondur?
Java'da arayüz değişkenleri neden varsayılan olarak statik ve sondur?
Yanıtlar:
Philip Shaw'un Java arayüz tasarımı SSS bölümünden:
Java arabirimleri kendi başlarına başlatılamadığından, arabirim değişkenleri statiktir; değişkenin değeri, içinde hiçbir örnek bulunmayan statik bir bağlamda atanmalıdır. Son değiştirici, arabirim değişkenine atanan değerin, program kodu tarafından yeniden atanamayan gerçek bir sabit olmasını sağlar.
static
Değiştirici için bu açıklama tamamen sahte. Bir sınıfın genel yönetim ortamı değişkenleri, arabiriminin bir parçasıdır ve interface
tıpkı yönetim ortamı yöntemlerinde olduğu gibi bir Java'da soyutlanmamalarının bir nedeni yoktur . Bir Java'nın interface
doğrudan somutlaştırılamaması önemli değildir - yine de uygulayan sınıf örneklerine sahip olabilirsiniz interface
ve belirli bir ortak örnek değişkenine sahip olmalarını gerektirebilir. final
Bununla ilgili olarak , bu hiç bir açıklama sunmuyor - sadece ne final
anlama geldiğini açıklıyor .
Arayüz doğrudan bir nesneye sahip olmadığından, bunlara erişmenin tek yolu bir sınıf / arayüz kullanmaktır ve bu nedenle arayüz değişkeni varsa statik olmalıdır, aksi takdirde dış dünyaya erişilemez. Statik olduğu için, sadece bir değeri tutabilir ve onu uygulayan herhangi bir sınıf onu değiştirebilir ve bu yüzden her şey dağınık olacaktır.
Dolayısıyla, eğer bir arayüz değişkeni varsa, dolaylı olarak statik, nihai ve açık bir şekilde halka açık olacaktır !!!
interface
. Bir sınıf, örnek değişkeni (arabirimin gerektirdiği gibi) bildirerek arabirimi uygular. Yapıcısı (veya başka bir yöntem) örnek değişkenini ayarlar. Sınıfın bir örneği başlatıldığında, örnek değişkenine erişebileceksiniz.
public : arayüzde bulunan yöntemler gibi tüm sınıflara erişilebilirlik için
static : arabirimin bir nesnesi olamaz, interfaceName.variableName ona veya doğrudan uygulayan sınıftaki değişkenName'e başvurmak için kullanılabilir.
nihai : sabit yapmak. 2 sınıf aynı arabirimi uygular ve her ikisine de değeri değiştirme hakkını verirseniz, var değerinin geçerli değerinde çakışma olur, bu nedenle yalnızca bir kez başlatmaya izin verilir.
Ayrıca tüm bu değiştiriciler bir arayüz için örtüktür, gerçekten herhangi birini belirtmeniz gerekmez.
( Bu felsefi bir cevap değil, daha pratik bir cevaptır ). Değiştirici gereksinimi static
açıktır ve bunlar başkaları tarafından cevaplanmıştır. Temel olarak, arayüzler somutlaştırılamadığından, alanlarına erişmenin tek yolu onları bir sınıf alanı yapmaktır -static
.
interface
Alanların otomatik olarak final
(sabit) hale gelmesinin nedeni , farklı uygulamaların yanlışlıkla diğer uygulamaların davranışını etkileyebilecek arabirim değişkeninin değerini değiştirmesini önlemektir. Bir interface
mülkün açıkça final
Java tarafından oluşturulmadığı aşağıdaki senaryoyu düşünün :
public interface Actionable {
public static boolean isActionable = false;
public void performAction();
}
public NuclearAction implements Actionable {
public void performAction() {
// Code that depends on isActionable variable
if (isActionable) {
// Launch nuclear weapon!!!
}
}
}
Şimdi, uygulayan başka bir sınıf Actionable
arabirim değişkeninin durumunu değiştirirse ne olacağını düşünün :
public CleanAction implements Actionable {
public void performAction() {
// Code that can alter isActionable state since it is not constant
isActionable = true;
}
}
Bu sınıflar classloader tek bir JVM içinde yüklenir, daha sonra davranışı NuclearAction
başka bir sınıf ile etkilenebilir, CleanAction
onun zaman performAction()
sonra çağırmak olduğuCleanAction
bu felaket bu durumda özellikle olabilir (aksi takdirde, aynı iplik ya da) yürütülür (anlamsal olarak bu).
A'nın her bir uygulamasının interface
bu değişkenleri nasıl kullanacağını bilmediğimizden , örtük olarak olmalıdırlar final
.
Çünkü başka bir şey uygulamanın bir parçasıdır ve arayüzler herhangi bir uygulamayı içeremez.
public interface A{
int x=65;
}
public interface B{
int x=66;
}
public class D implements A,B {
public static void main(String[] a){
System.out.println(x); // which x?
}
}
İşte çözüm.
System.out.println(A.x); // done
Arayüz değişkeninin statik olmasının bir nedeni olduğunu düşünüyorum.
Arayüz içindeki değişkenleri bildirmeyin.
static final
aslında statik ve nihai değişkenten önce yazılı görmüyorsunuz .
static - çünkü Arayüz herhangi bir örneğe sahip olamaz. ve son olarak - değiştirmemiz gerekmiyor.
Çünkü:
Static
: arayüzlerin nesnelerine sahip olamayacağımızdan, Object level üye değişkenlerini kullanmaktan kaçınmalı ve class level değişkenlerini yani static kullanmalıyız.
Final
: Değişkenler için belirsiz değerler olmamalıdır (Elmas problemi - Çoklu Kalıtım).
Ve dokümantasyon arayüzüne göre bir uygulama değil, bir sözleşmedir.
referans: Abhishek Jain'in quora'daki cevabı
Java, arabirimlerde soyut değişkenlere ve / veya yapıcı tanımlarına izin vermez. Çözüm: Arayüzünüzle uygulamanız arasında yalnızca soyut sınıfı genişleten soyut bir sınıf asın:
public interface IMyClass {
void methodA();
String methodB();
Integer methodC();
}
public abstract class myAbstractClass implements IMyClass {
protected String varA, varB;
//Constructor
myAbstractClass(String varA, String varB) {
this.varA = varA;
this.varB = VarB;
}
//Implement (some) interface methods here or leave them for the concrete class
protected void methodA() {
//Do something
}
//Add additional methods here which must be implemented in the concrete class
protected abstract Long methodD();
//Write some completely new methods which can be used by all subclasses
protected Float methodE() {
return 42.0;
}
}
public class myConcreteClass extends myAbstractClass {
//Constructor must now be implemented!
myClass(String varA, String varB) {
super(varA, varB);
}
//All non-private variables from the abstract class are available here
//All methods not implemented in the abstract class must be implemented here
}
Daha sonra diğer arabirimlerle birlikte uygulamak istemediğinizden EMİN iseniz, herhangi bir arabirim olmadan soyut bir sınıf da kullanabilirsiniz . Lütfen soyut bir sınıfın örneğini oluşturamayacağınızı ve önce onu genişletmeniz gerektiğini unutmayın.
("Korumalı" anahtar kelime, yalnızca genişletilmiş sınıfların bu yöntemlere ve değişkenlere erişebileceği anlamına gelir.)
spyro
Arayüz, değişmeyen, taşa oyulmuş, dolayısıyla nihai olan iki taraf arasında sözleşmedir. Bkz . Sözleşmeye Göre Tasarım .
Arayüz: Sistem gereksinimi hizmeti.
Arabirimde, değişken varsayılan olarak genel, statik, son erişim değiştirici tarafından atanır . Çünkü :
public: Arayüzün başka bir pakete yerleştirilmesi bazen olabilir. Bu nedenle, değişkenin projenin herhangi bir yerinden erişmesi gerekir.
statik: Böyle eksik bir sınıf nesne oluşturamaz. Bu yüzden projede değişkene nesne olmadan erişmemiz gerekiyor, böyleceinterface_filename.variable_name
final: Bir sınıfın birçok sınıf tarafından uygulandığını ve tüm sınıfların arayüz değişkenine erişmeye ve bunları güncellemeye çalıştığını varsayalım. Böylece veri değişiminde tutarsızlığa yol açar ve diğer tüm sınıfları etkiler. Bu yüzden erişim değiştiriciyi final ile bildirmek gerekir.
İçinde Java
, arayüz herhangi bir örnek değişkeni bildirmenize izin vermez. Bir arabirimde bildirilen bir değişkenin örnek değişkeni olarak kullanılması, bir derleme zamanı hatası döndürür.
static final
Bir örnek değişkeninden farklı olan sabit değişkeni bildirebilirsiniz .
Arayüz herhangi bir sınıf tarafından uygulanabilir ve bu değer orada uygulayıcı sınıflardan biri tarafından değiştirilirse, diğer uygulayıcı sınıflar için yanıltıcı olur. Arayüz temel olarak iki çekirdeklenmiş ancak farklı varlığı birleştirmek için bir referanstır. Bu nedenle arayüz içindeki bildirme değişkeni dolaylı olarak nihai ve ayrıca statik olacaktır çünkü arayüz anlık olamaz.
Arayüz tanımlı ve diğer sınıfların uyguladığı bir web uygulamasını düşünün. Değişkenlere erişmek için bir arabirim örneği oluşturamadığınız için statik bir anahtar kelimeye sahip olmanız gerekir. Statik olduğundan, değerdeki herhangi bir değişiklik, onu uygulayan diğer örnekleri yansıtacaktır. Bunu önlemek için onları nihai olarak tanımlarız.
Eclipse'de yeni denedim, arayüzdeki değişken varsayılan olarak sondur, bu yüzden değiştiremezsiniz. Üst sınıfla karşılaştırıldığında, değişkenler kesinlikle değiştirilebilir. Neden? Benim açımdan, sınıftaki değişken, çocuklar tarafından miras alınacak bir özelliktir ve çocuklar bunu gerçek ihtiyaçlarına göre değiştirebilir. Aksine, arayüz nitelik değil, sadece davranışı tanımlar. Arabirimde değişkenleri koymanın tek nedeni, onları bu arabirimle ilgili sabitler olarak kullanmaktır. Yine de, aşağıdaki alıntıya göre bu iyi bir uygulama değildir:
"Sabitleri bir arayüze yerleştirmek, Java'nın ilk günlerinde popüler bir teknikti, ancak şimdi birçok kişi bunu arayüzlerin tatsız bir kullanımı olarak görüyor, çünkü arayüzler, verileri değil, bir nesnenin sağladığı hizmetler ile ilgilenmelidir. bir sınıf, genellikle bir uygulama ayrıntısıdır, ancak bunları bir arayüze yerleştirmek onları sınıfın genel API'sına yükseltir. "
Ben de statik koymak ya da hiç fark etmez denedim. Kod aşağıdaki gibidir:
public interface Addable {
static int count = 6;
public int add(int i);
}
public class Impl implements Addable {
@Override
public int add(int i) {
return i+count;
}
}
public class Test {
public static void main(String... args) {
Impl impl = new Impl();
System.out.println(impl.add(4));
}
}