Java neden statik yöntemlerin geçersiz kılınmasına izin vermiyor?


534

Statik yöntemleri geçersiz kılmak neden mümkün değildir?

Mümkünse, lütfen bir örnek kullanın.


3
Çoğu OOP dili buna izin vermiyor.
jmucchiello

7
@jmucchiello: cevabımı gör. Seninle aynı şekilde düşünüyordum, ama sonra Ruby / Smalltalk 'sınıf' yöntemlerini öğrendim ve bu yüzden bunu yapan başka gerçek OOP dilleri var.
Kevin Brock

5
@jmucchiello çoğu OOP dili gerçek OOP dili değildir (bence Smalltalk)
mathk


1
Java'nın statik yöntemlere yapılan çağrıları derleme zamanında çözmesi olabilir. Bu yüzden yazmış olsanız Parent p = new Child()ve p.childOverriddenStaticMethod()derleyici Parent.childOverriddenStaticMethod()referans türüne bakarak çözecektir .
Manoj

Yanıtlar:


494

Geçersiz kılma, bir sınıf örneğine sahip olmasına bağlıdır. Polimorfizmin amacı, bir sınıfı alt sınıflandırabilmenizdir ve bu alt sınıfları uygulayan nesneler, üst sınıfta tanımlanan (ve alt sınıflarda geçersiz kılınan) aynı yöntemler için farklı davranışlara sahip olacaktır. Statik bir yöntem, sınıfın herhangi bir örneğiyle ilişkilendirilmez, bu nedenle kavram uygulanabilir değildir.

Java'nın tasarımını etkileyen, bunu etkileyen iki husus vardı. Birisi performansla ilgili bir kaygıydı: Smalltalk'ın çok yavaş olduğuna dair çok fazla eleştiri vardı (çöp toplama ve polimorfik çağrılar bunun bir parçasıydı) ve Java'nın yaratıcıları bundan kaçınmaya kararlıydı. Bir diğeri, Java için hedef kitlenin C ++ geliştiricileri olduğu kararıydı. Statik yöntemlerin C ++ programcıları için aşina olma avantajına sahip oldukları şekilde çalışmasını sağlamak ve aynı zamanda çok hızlıydı, çünkü hangi yöntemi çağıracağınızı anlamak için çalışma zamanına kadar beklemeye gerek yoktur.


18
... ancak Java'da yalnızca "doğru". Örneğin, Scala'nın "statik sınıflar" (buna denir objects) eşdeğeri yöntemlerin aşırı yüklenmesine izin verir.

32
Objective-C sınıf yöntemlerinin geçersiz kılınmasına da izin verir .
Richard

11
Derleme zamanı türü hiyerarşisi ve çalışma zamanı türü hiyerarşisi vardır. Statik bir yöntem çağrısının, neden olduğu durumlarda, çalışma zamanı türü hiyerarşisinden neden faydalanmadığını sormak mantıklıdır. Java'da bu, bir nesneden ( obj.staticMethod()) izin verilen ve derleme zamanı türlerini kullanan statik bir yöntem çağrıldığında olur . Statik çağrı bir sınıfın statik olmayan bir yöntemindeyse, "current" nesnesi sınıfın türetilmiş bir türü olabilir - ancak türetilen türlerde tanımlanan statik yöntemler dikkate alınmaz (çalışma zamanı türündedir hiyerarşi).
Steve Powell

18
Bunu açıkça belirtmeliydim: kavramın geçerli olmadığı doğru değil .
Steve Powell

13
Bu cevap doğru olsa da, OP'nin ve dolayısıyla burada kendim ve diğerlerinin beklentilerini karşılamak için nasıl olması gerektiğinden ya da nasıl olabileceğinden daha çok "nasıl" olduğuna benziyor. "Bu şekilde" dışında statik yöntemlerin geçersiz kılınmasına izin vermemek için somut bir neden yoktur. Kişisel olarak bir kusur olduğunu düşünüyorum.
RichieHH

186

Şahsen bu Java tasarımında bir kusur olduğunu düşünüyorum. Evet, evet, statik yöntemler bir sınıfa vb. Bağlıyken statik olmayan yöntemlerin bir örneğe eklendiğini anlıyorum. Yine de aşağıdaki kodu göz önünde bulundurun:

public class RegularEmployee {
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

    public BigDecimal calculateBonus() {
        return salary.multiply(getBonusMultiplier());
    }

    /* ... presumably lots of other code ... */
}

public class SpecialEmployee extends RegularEmployee {
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

Bu kod beklediğiniz gibi çalışmaz. Yani, SpecialEmployee normal çalışanlar gibi% 2 bonus kazanır. Ancak "statik" leri kaldırırsanız, SpecialEmployee% 3 bonus kazanır.

(Kuşkusuz, bu örnek, gerçek hayatta bonus çarpanının sabit kodlu değil bir yerde bir veritabanında olmasını isteyeceğiniz için kötü kodlama tarzıdır. noktayla alakasız kod.)

GetBonusMultiplier'ı statik hale getirmek isteyebileceğiniz benim için oldukça makul görünüyor. Belki de, her kategoride bir çalışanın bir örneğine ihtiyaç duymadan, tüm çalışan kategorileri için bonus çarpanını görüntülemek isteyebilirsiniz. Bu örnek örnekleri aramanın anlamı ne olabilir? Yeni bir çalışan kategorisi oluşturuyor ve buna henüz bir çalışan atanmamışsa ne olur? Bu oldukça mantıklı bir statik işlevdir.

Ama işe yaramıyor.

Ve evet, evet, çalışması için yukarıdaki kodu yeniden yazmak için herhangi bir sayıda yol düşünebilirsiniz. Demek istediğim, çözülemez bir sorun yarattığı değil, aynı zamanda dikkatsiz bir programcı için bir tuzak yarattığıdır, çünkü mantıklı bir insanın beklediği gibi dil davranmaz.

Belki bir OOP dili için bir derleyici yazmaya çalışırsam, statik fonksiyonların geçersiz kılınabilmesi için neden uygulandığını hızlı bir şekilde anlayabilirdim.

Ya da Java'nın bu şekilde davranmasının iyi bir nedeni olabilir. Herkes bu davranış bir avantaj, bu daha kolay hale getirilen bir sorun kategorisine işaret edebilir? Demek istediğim, beni sadece Java dil spesifikasyonuna yönlendirmeyin ve "bakın, bu nasıl davrandığını belgeledi" deyin. Bunu biliyorum. Ancak bu şekilde davranması için iyi bir neden var mı? (Açıkça "doğru çalışmasını sağlamak çok zordu" ...)

Güncelleme

@VicKirk: Bunun "kötü tasarım" olduğunu söylüyorsanız, Java'nın statik işlemleri nasıl gerçekleştirdiğine uymuyorsa, cevabım "Tabii ki, tabii ki". Orijinal yazımda söylediğim gibi, işe yaramıyor. Ancak, bunun çalıştığı bir dille, yani statikin sanal işlevler gibi geçersiz kılınabileceği bir dille temelde yanlış bir şey olacağı anlamında kötü bir tasarım olduğunu kastediyorsanız, bunun bir şekilde bir belirsizlik getireceği veya verimli bir şekilde ya da böyle bir şekilde, "Neden? Kavramın nesi yanlış?"

Sanırım verdiğim örnek yapmak çok doğal bir şey. Herhangi bir örnek verilere bağlı olmayan ve çok makul bir örnek bağımsız çağırmak yanı sıra bir örnek yöntemi içinde aramak isteyen bir işlevi olan bir sınıf var. Bu neden işe yaramıyor? Bu duruma yıllar içinde oldukça fazla rastladım. Uygulamada, işlevi sanal hale getirerek ve sonra hayattaki tek amacı çağrıyı kukla bir örnekle sanal yönteme geçiren statik bir yöntem olmak olan statik bir yöntem oluşturarak bu sorunu çözüyorum. Buraya ulaşmak için çok dolambaçlı bir yol gibi görünüyor.


11
@Bemrose: Ama bu benim amacım: Bunu yapmama neden izin vermemeliyim? Belki de bir "statik" in ne yapması gerektiğine dair sezgisel konseptim sizinkinden farklıdır, ama temelde statiki statik olabilecek CAN olabilir, çünkü herhangi bir örnek veri kullanmadığı ve isteyebilirsiniz çünkü statik olması gerekir bir örnekten bağımsız olarak çağırmak için. Statik açıkça bir sınıfa bağlıdır: Integer.valueOf'un Integers'a ve Double.valueOf'un Çiftler'e bağlı olmasını bekliyorum.
Jay

9
@ewernli & Bemrose: Evet evet, işte böyle. Bunu tartışmıyorum. Örneğimdeki kod çalışmadığından, elbette yazmaya çalışmayacağım. Benim sorum neden böyle olduğu. (Bunun iletişim kurmadığımız konuşmalardan birine dönüşmesinden korkuyorum. "Affedersiniz Bay Satıcı, bunlardan birini kırmızıya getirebilir miyim?" "Hayır, maliyeti 5 $." "Evet, bunun maliyetini biliyorum 5 dolar, ama kırmızı bir tane alabilir miyim? "" Efendim, size sadece 5 dolara mal olduğunu söylemiştim. "" Tamam, fiyatı biliyorum, ama rengi soruyordum. "" Sana fiyatı zaten söyledim! " vb.)
Jay

6
Sonuçta bu kod kafa karıştırıcı olduğunu düşünüyorum. Örneğin parametre olarak iletilip iletilmediğini düşünün. Sonra çalışma zamanı örneğinin hangi statik yöntemin çağrıldığını dikte etmesi gerektiğini söylüyorsunuz. Bu temelde mevcut örneğe paralel olarak tamamen ayrı bir hiyerarşi yapar. Şimdi, bir alt sınıf statik olmayanla aynı yöntem imzasını tanımlarsa ne olur? Kuralların işleri oldukça karmaşık hale getireceğini düşünüyorum. Java'nın kaçınmaya çalıştığı tam da bu tür dil komplikasyonlarıdır.
Yishai

6
@Yishai: RE "Çalışma zamanı örneği, hangi statik yöntemin çağrıldığını belirler": Kesinlikle. Neden bir sanal ile yapabileceğiniz bir statik ile hiçbir şey yapamıyorsunuz anlamıyorum. "Ayrı hiyerarşi": Bunu aynı hiyerarşinin bir parçası yap diyebilirim. Statik aynı hiyerarşiye neden dahil edilmiyor? "Abonelik aynı imzayı statik olmayan olarak tanımlar": Sanırım yasa dışı olduğu gibi, benzer bir imzası olan ancak farklı bir dönüş türüne sahip bir alt sınıfı geçersiz kılmak veya başka bir istisna türü olmayan bir işlevi geçersiz kılmak gibi yasadışı olacağını düşünüyorum. ebeveyn atar veya daha dar bir kapsama sahip olur.
Jay

28
Bence Jay'in bir anlamı var - statiğin geçersiz kılınamayacağını keşfettiğimde beni de şaşırttı. Kısmen, eğer A yöntemiyle someStatic()ve B A'yı genişletirse, A'daki yönteme B.someMethod() bağlanırsa . Daha sonra someStatic()B'ye A.someStatic()eklersem, arama kodunu yeniden derleyene kadar arama kodu hala çağırır . Ayrıca derleme değil bağlanır, çünkü çalışma zamanı türü değil bInstance.someStatic(), bildirilen bInstance türü kullanan beni şaşırttı , bu nedenle A bInstance; ... bInstance.someStatic()eğer B.someStatic () varsa A.someStatic () çağırır.
Lawrence Dol

42

Kısa cevap: tamamen mümkündür, ancak Java bunu yapmaz.

Java'daki mevcut durumu gösteren bazı kodlar :

Dosya Base.java:

package sp.trial;
public class Base {
  static void printValue() {
    System.out.println("  Called static Base method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Base method.");
  }
  void nonLocalIndirectStatMethod() {
    System.out.println("  Non-static calls overridden(?) static:");
    System.out.print("  ");
    this.printValue();
  }
}

Dosya Child.java:

package sp.trial;
public class Child extends Base {
  static void printValue() {
    System.out.println("  Called static Child method.");
  }
  void nonStatPrintValue() {
    System.out.println("  Called non-static Child method.");
  }
  void localIndirectStatMethod() {
    System.out.println("  Non-static calls own static:");
    System.out.print("  ");
    printValue();
  }
  public static void main(String[] args) {
    System.out.println("Object: static type Base; runtime type Child:");
    Base base = new Child();
    base.printValue();
    base.nonStatPrintValue();
    System.out.println("Object: static type Child; runtime type Child:");
    Child child = new Child();
    child.printValue();
    child.nonStatPrintValue();
    System.out.println("Class: Child static call:");
    Child.printValue();
    System.out.println("Class: Base static call:");
    Base.printValue();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Child:");
    child.localIndirectStatMethod();
    System.out.println("Object: static/runtime type Child -- call static from non-static method of Base:");
    child.nonLocalIndirectStatMethod();
  }
}

Bunu çalıştırırsanız (Mac 1.6'da, Eclipse'den Java 1.6 kullanarak yaptım) şunları elde edersiniz:

Object: static type Base; runtime type Child.
  Called static Base method.
  Called non-static Child method.
Object: static type Child; runtime type Child.
  Called static Child method.
  Called non-static Child method.
Class: Child static call.
  Called static Child method.
Class: Base static call.
  Called static Base method.
Object: static/runtime type Child -- call static from non-static method of Child.
  Non-static calls own static.
    Called static Child method.
Object: static/runtime type Child -- call static from non-static method of Base.
  Non-static calls overridden(?) static.
    Called static Base method.

Burada, sürpriz olabilecek (ve sorunun hakkında olduğu) sadece vakalar ilk durum gibi görünüyor:

"Çalışma zamanı türü, bir nesne örneği ( obj.staticMethod()) ile çağrıldığında bile hangi statik yöntemlerin çağrıldığını belirlemek için kullanılmaz ."

ve son dava:

"Bir sınıfın nesne yönteminin içinden statik bir yöntem çağırırken, seçilen statik yöntem , nesnenin çalışma zamanı türünü tanımlayan sınıftan değil , sınıfın kendisinden erişilebilir yöntemdir ."

Bir nesne örneği ile arama

Statik çağrı derleme zamanında çözümlenirken, statik olmayan yöntem çağrısı çalışma zamanında çözümlenir. Statik yöntemler miras alınsa da (ebeveynden) geçersiz kılınmadıklarına (çocuk tarafından) dikkat edin. Aksi takdirde bu bir sürpriz olabilir.

Bir nesne yönteminden arama

Nesne yöntemi çağrıları çalışma zamanı türü kullanılarak çözümlenir, ancak statik ( sınıf ) yöntem çağrıları derleme zamanı (bildirilen) türü kullanılarak çözümlenir.

Kuralları değiştirme

Bu kuralları değiştirmek için, çağrılan örnekteki son Child.printValue()çağrının, derleme zamanında çağrıyı nesnenin bildirilen sınıfıyla çözümlemesi yerine derleyici yerine statik çağrılara bir tür sağlanmalıdır. bağlamı). Statik çağrılar, tıpkı nesne yöntemi çağrılarının bugün yaptığı gibi çağrıyı çözmek için (dinamik) tür hiyerarşisini kullanabilir.

Bu kolayca yapılabilir (Java: -O değiştirirsek) ve hiç de mantıksız değildir, ancak bazı ilginç hususlar vardır.

Ana düşünce, hangi statik yöntem çağrılarının bunu yapması gerektiğine karar vermemiz gerektiğidir .

Şu anda Java, obj.staticMethod()çağrıların ObjectClass.staticMethod()çağrılarla (normalde bir uyarı ile) değiştirildiği dilde "tuhaflığa" sahiptir . [ Not: ObjectClass derleme zamanı türüdür obj.] Bunlar, çalışma zamanı türünü alarak bu şekilde geçersiz kılmak için iyi adaylar olacaktır obj.

Eğer yapsaydık, yöntem gövdelerinin okunmasını zorlaştırırdı: bir üst sınıftaki statik çağrılar, dinamik olarak "yeniden yönlendirilebilir". Bundan kaçınmak için, statik adı bir sınıf adıyla çağırmamız gerekir ve bu da çağrıları derleme zamanı tür hiyerarşisiyle daha açık bir şekilde çözülür (şimdi olduğu gibi).

Statik bir yöntemi çağırmanın diğer yolları daha zordur: çalışma zamanı türünü almakla this.staticMethod()aynı anlama gelmelidir . Bununla birlikte, bu durum, mevcut programlarla süssüz (görünüşte yerel) statik yöntemleri çağıran (muhtemelen eşdeğerdir ) bazı baş ağrılarına neden olabilir .obj.staticMethod()thisthis.method()

Peki ya süssüz aramalar staticMethod()? Bugünle aynı şeyi yapmalarını ve ne yapılacağına karar vermek için yerel sınıf bağlamını kullanmalarını öneriyorum. Aksi takdirde büyük bir karışıklık ortaya çıkar. Tabii ki demektir method()anlamına gelecektir this.method()eğer methodbir statik olmayan yöntem olduğunu ve ThisClass.method()eğer methodstatik bir metod idi. Bu başka bir karışıklık kaynağı.

Dikkat edilecek diğer noktalar

Biz bu davranışı değişti (ve statik aramaları potansiyel dinamik yerel olmayan yapılmış), biz muhtemelen anlamını tekrar istediğiniz final, privateve protectedeleme olarak staticbir sınıf yöntemleri. O zaman hepimiz private staticve public finalyöntemlerin geçersiz kılınmadığına ve bu nedenle derleme zamanında güvenli bir şekilde çözülebileceğine ve yerel referanslar olarak okumak için "güvenli" olduğumuza alışmalıyız.


"Yapsaydık yöntem gövdelerinin okunmasını zorlaştırır: bir üst sınıftaki statik çağrılar, dinamik olarak" yeniden yönlendirilebilir ". Doğru, ama şimdi sıradan statik olmayan fonksiyon çağrıları ile olan tam olarak budur. Bu rutin olarak sıradan sanal fonksiyonlar için olumlu bir özellik olarak lanse edilir, bir problem değildir.
Jay

25

Aslında yanılmışız.
Java, varsayılan olarak statik yöntemleri geçersiz kılmanıza izin vermese de, Java'daki Sınıf ve Yöntem sınıflarının belgelerine tam olarak bakarsanız, aşağıdaki geçici çözümü uygulayarak statik yöntemleri geçersiz kılmanın bir yolunu bulabilirsiniz:

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;

class RegularEmployee {

    private BigDecimal salary = BigDecimal.ONE;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }
    public BigDecimal calculateBonus() {
        return salary.multiply(this.getBonusMultiplier());
    }
    public BigDecimal calculateOverridenBonus() {
        try {
            // System.out.println(this.getClass().getDeclaredMethod(
            // "getBonusMultiplier").toString());
            try {
                return salary.multiply((BigDecimal) this.getClass()
                    .getDeclaredMethod("getBonusMultiplier").invoke(this));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }
    // ... presumably lots of other code ...
}

final class SpecialEmployee extends RegularEmployee {

    public static BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
}

public class StaticTestCoolMain {

    static public void main(String[] args) {
        RegularEmployee Alan = new RegularEmployee();
        System.out.println(Alan.calculateBonus());
        System.out.println(Alan.calculateOverridenBonus());
        SpecialEmployee Bob = new SpecialEmployee();
        System.out.println(Bob.calculateBonus());
        System.out.println(Bob.calculateOverridenBonus());
    }
}

Ortaya çıkan çıktı:

0.02
0.02
0.02
0.03

elde etmeye çalıştıklarımız :)

Üçüncü değişkeni Carl'ı RegularEmployee olarak tanımlasak ve buna SpecialEmployee örneği atadığımızda bile, ilk durumda RegularEmployee yöntemini ve ikinci durumda SpecialEmployee yöntemini çağrıyoruz.

RegularEmployee Carl = new SpecialEmployee();

System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());

sadece çıkış konsoluna bakın:

0.02
0.03

;)


9
Evet yansıma hemen hemen bir kişinin yapabileceği tek şey - ama soru tam olarak bu değil - burada olsa da yararlı
Mr_and_Mrs_D

1
Bu cevap, şu ana kadar tüm Java konularında gördüğüm en büyük hack'tir. Hala okumak için eğlenceliydi :)
Andrejs

19

Statik yöntemler JVM tarafından genel olarak ele alınır, hiçbir nesne örneğine bağlı değildir.

Sınıf nesnelerinden (Smalltalk gibi dillerde olduğu gibi) statik yöntemleri çağırabiliyorsanız kavramsal olarak mümkün olabilir, ancak Java'da durum böyle değildir.

DÜZENLE

Statik yöntemi aşırı yükleyebilirsiniz , sorun değil. Ancak , sınıf birinci sınıf bir nesne olmadığından statik bir yöntemi geçersiz kılamazsınız. Yansıma, bir nesnenin sınıfını çalışma zamanında almak için kullanabilirsiniz, ancak aldığınız nesne sınıf hiyerarşisine paralel değildir.

class MyClass { ... }
class MySubClass extends MyClass { ... }

MyClass obj1 = new MyClass();
MySubClass obj2 = new MySubClass();

ob2 instanceof MyClass --> true

Class clazz1 = obj1.getClass();
Class clazz2 = obj2.getClass();

clazz2 instanceof clazz1 --> false

Sınıfları yansıtabilirsiniz, ama orada durur. Kullanarak değil clazz1.staticMethod(), kullanarak statik bir yöntem çağırırsınız MyClass.staticMethod(). Statik bir yöntem bir nesneye bağlı değildir ve dolayısıyla statik bir yöntemde thisne de ne superbir kavram vardır . Statik bir yöntem global bir işlevdir; sonuç olarak, polimorfizm nosyonu da yoktur ve bu nedenle, yöntem geçersiz kılma anlamsızdır.

Ancak bu MyClass, Smalltalk'taki gibi bir yöntemi çağırdığınız çalışma zamanında bir nesne olsaydı mümkün olabilir (veya belki bir yorum olarak JRuby, ama JRuby hakkında hiçbir şey bilmiyorum).

Evet, bir şey daha. Bir nesne aracılığıyla statik bir yöntem çağırabilirsiniz, obj1.staticMethod()ancak bu gerçekten sözdizimsel şeker için MyClass.staticMethod()kaçınılmalıdır. Genellikle modern IDE'de bir uyarı verir. Bu kısayola neden izin verdiklerini bilmiyorum.


5
Ruby gibi birçok modern dilin bile sınıf yöntemleri vardır ve bunları geçersiz kılmaya izin verir.
Chandra Sekar

3
Sınıflar Java'da nesne olarak bulunur. "Sınıf" sınıfına bakınız. MyObject.getClass () diyebilirim ve bana uygun sınıf nesnesinin bir örneğini döndürür.
Jay

5
Sınıfın yalnızca bir "tanımını" alırsınız - sınıfın kendisini değil. Ama fark çok ince.
ewernli

Hâlâ sınıfınız var ancak sanal makinede (sınıf yükleyicinin yanında) gizlidir, kullanıcının buna neredeyse erişimi yoktur.
mathk

Kullanmak için clazz2 instanceof clazz1düzgün yerine kullanabilirsiniz class2.isAssignableFrom(clazz1)senin örnekte gerçek döneceğini düşünüyoruz, hangi.
Simon Forsberg

14

Yöntem geçersiz kılma, dinamik gönderme ile mümkün olur , yani bir nesnenin bildirilen türü davranışını değil, çalışma zamanı türünü belirler:

Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"

Her ikisi de lassieve kermittür nesnesi olarak bildirilse de Animal, davranışları (yöntemi .speak()) değişir çünkü dinamik gönderme , yöntem çağrısını derleme zamanında değil, yalnızca çalışma zamanında bir uygulamaya bağlar.speak() .

Şimdi, burada staticanahtar kelime anlamlı olmaya başlar: "statik" kelimesi "dinamik" için bir zıttır. Bu nedenle, statik yöntemleri geçersiz kılmamanızın nedeni, statik üyelerde dinamik gönderme olmamasıdır - çünkü statik kelimenin tam anlamıyla "dinamik değil" anlamına gelir. Dinamik olarak gönderildiyse (ve dolayısıyla geçersiz kılınabilirlerse), staticanahtar kelime artık bir anlam ifade etmeyecektir.


11

Evet. Pratik olarak Java statik yöntemi geçersiz kılmaya izin verir ve Java'da statik bir yöntemi geçersiz kılarsanız teorik olarak Hayır derler ve sorunsuz çalışır, ancak Java'nın temel özelliği olan Polimorfizmi kaybeder. Kendinizi derlemeye ve çalıştırmaya çalışmanın mümkün olmadığını Her Yerde okuyacaksınız. cevabını alacaksın. Örneğin, Sınıf Hayvanınız varsa ve statik bir yöntem eat () ise ve Alt Sınıfındaki bu statik yöntemi Geçersiz kılsanız, Köpek olarak adlandıralım. O zaman bir Hayvan Referansı'na bir Köpek nesnesi Atadığınızda ve Java Köpeğinin yiyeceğine () göre eat () çağrıldığında çağrılmalı, ancak statik Geçersiz Kılan Hayvanların yiyeceği () çağrılmalıdır.

class Animal {
    public static void eat() {
        System.out.println("Animal Eating");
    }
}

class Dog extends Animal{
    public static void eat() {
        System.out.println("Dog Eating");
    }
}

class Test {
    public static void main(String args[]) {
       Animal obj= new Dog();//Dog object in animal
       obj.eat(); //should call dog's eat but it didn't
    }
}


Output Animal Eating

Java'nın Polimorfizm İlkesine göre Çıktı olmalıdır Dog Eating.
Ancak sonuç farklıydı çünkü Polimorfizmi desteklemek için Java, Geç Bağlama'yı kullanır; bu, yöntemlerin yalnızca çalışma zamanında çağrıldığı anlamına gelir, ancak statik yöntemler durumunda değil. Statik yöntemlerde derleyici yöntemleri çalışma zamanı yerine derleme zamanında çağırır, bu nedenle nesneye göre bir referans içeren bir referansa değil, referansa göre yöntemler alırız. 't.


3
Nesneden statik yöntemler çağırmak kötü bir uygulamadır.
Dmitry Zagorulkin

6

geçersiz kılma, örneğin polimorfik davranışı desteklemek için üyeler için ayrılmıştır. statik sınıf üyeleri belirli bir örneğe ait değildir. bunun yerine, statik üyeler sınıfa aittir ve sonuç olarak geçersiz kılma desteklenmez, çünkü alt sınıflar statik üyeleri değil yalnızca korumalı ve genel yönetim ortamı üyelerini devralır. Alternatif bir yaklaşımı değerlendirmek için bir arayüz ve araştırma fabrikası ve / veya strateji tasarım modelleri tanımlamak isteyebilirsiniz.


1
Bunu zaten kapsayan ve bunların kavramsal düzeyde geçersiz kılma istatistiklerini iskonto etmek için yeterli neden olmadığını açıkça belirten diğer cevaplardan hiçbirini okumadınız. İşe yaramadığını biliyoruz. Statik yöntemlerin geçersiz
kılınmasını

Richard, diyelim ki 4 yıl önce bu soruya cevap verdiğimde, bu cevapların çoğunun gönderilmediğini, bu yüzden bir eşek olmayın! Dikkatle okumadığımı iddia etmeye gerek yok. Ayrıca, sadece Java ile ilgili geçersiz kılmayı tartıştığımızı okumadınız. Diğer dillerde neler olabileceğini kim önemsiyor. Alakasız. Git başka bir yere trol. Yorumunuz bu konuya hiçbir değer katmıyor.
Athens Holloway

6

Java'da (ve birçok OOP dilinde, ancak herkes için konuşamıyorum; ve bazılarında hiç statik yok) tüm yöntemlerin sabit bir imzası var - parametreler ve türler. Sanal bir yöntemde ilk parametre ima edilir: nesnenin kendisine bir başvuru ve nesnenin içinden çağrıldığında derleyici otomatik olarak ekler this.

Statik yöntemler için bir fark yoktur - hala sabit bir imzası vardır. Ancak, statik yöntemi bildirerek, derleyicinin bu imzanın başına ima edilen nesne parametresini içermemesi gerektiğini açıkça belirtmişsinizdir. Bu nedenle, bunu çağıran diğer kodlar yığındaki bir nesneye başvuru yapmaya çalışmamalıdır . Eğer bunu yaparsa, parametreler yığın üzerinde yanlış yerde - birer birer kaydırılır - olacağından, yöntem yürütme çalışmaz.

İkisi arasındaki bu farktan dolayı; sanal yöntemlerin her zaman bağlam nesnesine (yani this) bir referansı vardır, bu nedenle öbek içinde nesnenin o örneğine ait olan herhangi bir şeye başvurmak mümkündür. Ancak statik yöntemlerle, başvuru geçmediği için, bağlam bilinmediği için bu yöntem herhangi bir nesne değişkenine ve yönteme erişemez.

Java'nın tanımı, statik veya sanal her yöntem için bir nesne bağlamının geçeceği şekilde değiştirmesini isterseniz, aslında yalnızca sanal yöntemlere sahip olursunuz.

Birisi op'a bir yorumda sorduğu gibi - bu özelliği istemenin sebebi ve amacı nedir?

Ruby'yi pek bilmiyorum, bu OP tarafından belirtildiği gibi, biraz araştırma yaptım. Ruby sınıflarında gerçekten özel bir nesne türü olduğunu ve (hatta dinamik olarak) yeni yöntemler oluşturabildiğini görüyorum. Sınıflar Ruby'deki tam sınıf nesnelerdir, Java'da değildirler. Bu, Java (veya C #) ile çalışırken kabul etmeniz gereken bir şeydir. Bunlar dinamik diller değil, ancak C # bazı dinamik formlar ekliyor. Gerçekte, Ruby bulabildiğim kadarıyla "statik" yöntemlere sahip değil - bu durumda bunlar singleton sınıfı nesnesindeki yöntemler. Daha sonra bu singletonu yeni bir sınıfla geçersiz kılabilirsiniz ve önceki sınıf nesnesindeki yöntemler yeni sınıfta tanımlananları çağırır (doğru?). Dolayısıyla, orijinal sınıf bağlamında bir yöntem çağırdıysanız, yine de yalnızca orijinal statikleri yürütür, ancak türetilmiş sınıfta bir yöntem çağrıldığında, üst veya alt sınıftan yöntemler çağrılır. İlginç ve bunda bir değer görebiliyorum. Farklı bir düşünce modeli gerektirir.

Java'da çalıştığınız için, bu şekilde bir şeyler yapmanız gerekir. Bunu neden yaptılar? Muhtemelen mevcut teknolojiyi ve anlayışı temel alarak o zamanki performansı artırmak. Bilgisayar dilleri sürekli gelişmektedir. Yeterince geriye gidin ve OOP diye bir şey yoktur. Gelecekte başka yeni fikirler olacak.

EDIT : Bir yorum daha. Şimdi farkları görüyorum ve kendimi Java / C # geliştiricisi olarak, Ruby gibi bir dilden geliyorsanız Java geliştiricilerinden aldığınız cevapların neden kafa karıştırıcı olabileceğini anlayabiliyorum. Java staticyöntemleri Ruby classyöntemleriyle aynı değildir . Java geliştiricileri, çoğunlukla Ruby / Smalltalk gibi bir dille çalışanların aksine, bunu anlamakta zorlanacaklar. Java'nın statik yöntemler hakkında konuşmanın başka bir yolu olarak "sınıf yöntemini" kullanması da bunun nasıl kafa karıştırıcı olabileceğini görebiliyorum, ancak aynı terim Ruby tarafından farklı şekilde kullanılıyor. Java'nın Ruby stili sınıf yöntemleri yoktur (üzgünüm); Ruby, C'de bulunan gerçekten eski prosedürel stil fonksiyonları olan Java tarzı statik yöntemlere sahip değildir.

Bu arada - soru için teşekkürler! Bugün sınıf yöntemleri (Ruby stili) hakkında yeni bir şey öğrendim.


1
Elbette, Java'nın bir "Sınıf" nesnesini statik yöntemlere gizli bir parametre olarak iletememesinin bir nedeni yoktur. Sadece bunu yapmak için tasarlanmamıştı.
jmucchiello

6

Eh ... Geçersiz bir yöntemin Java'da nasıl davranması gerektiği perspektifinden düşünürseniz cevap HAYIR. Ancak, statik bir yöntemi geçersiz kılmaya çalışırsanız herhangi bir derleyici hatası almazsınız. Bu, geçersiz kılmaya çalışırsanız, Java bunu yapmanıza engel olmaz; ancak statik olmayan yöntemlerle elde ettiğiniz etkiyi kesinlikle elde edemezsiniz. Java'da geçersiz kılma, belirli yöntemin, nesnenin çalışma zamanı türüne göre çağrılması anlamına gelir, derleme zamanı türüne değil (geçersiz kılınmış statik yöntemlerde olduğu gibi). Tamam ... neden garip davrandıklarına dair herhangi bir tahmin var mı? Sınıf metodları olduklarından ve bunlara erişim derleme zamanı boyunca daima derleme zamanı türü bilgileri kullanılarak çözümlendiğinden.

Örnek : Statik bir yöntemi geçersiz kılmaya çalışırsak ne olacağını görmeye çalışalım: -

class SuperClass {
// ......
public static void staticMethod() {
    System.out.println("SuperClass: inside staticMethod");
}
// ......
}

public class SubClass extends SuperClass {
// ......
// overriding the static method
public static void staticMethod() {
    System.out.println("SubClass: inside staticMethod");
}

// ......
public static void main(String[] args) {
    // ......
    SuperClass superClassWithSuperCons = new SuperClass();
    SuperClass superClassWithSubCons = new SubClass();
    SubClass subClassWithSubCons = new SubClass();

    superClassWithSuperCons.staticMethod();
    superClassWithSubCons.staticMethod();
    subClassWithSubCons.staticMethod();
    // ...
}
}

Çıktı : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod

Çıktının ikinci satırına dikkat edin. StaticMethod geçersiz kılınmış olsaydı, bu satır, 'SuperClass' olarak değil, Çalışma Zamanı Türü'nün bir nesnesindeki 'staticMethod ()' u çağırdığımız için üçüncü satırla aynı olmalıdır. Bu, statik yöntemlerin her zaman yalnızca derleme zamanı türü bilgileri kullanılarak çözümlendiğini doğrular.


5

Genel olarak statik yöntemleri 'geçersiz kılmaya' izin vermek mantıklı değildir, çünkü çalışma zamanında hangisini arayacağınızı belirlemenin iyi bir yolu yoktur. Çalışan örneğini alırsak, RegularEmployee.getBonusMultiplier () öğesini çağırırsak - hangi yöntemin yürütülmesi gerekir?

Java söz konusu olduğunda, bir nesne örneği aracılığıyla çağrıldıkları sürece statik yöntemleri 'geçersiz kılmanın' mümkün olduğu bir dil tanımı düşünülebilir. Bununla birlikte, tüm yapmanız gereken, gerçekten herhangi bir fayda sağlamadan dile fazlalık ekleyerek düzenli sınıf yöntemlerini yeniden uygulamaktır.


2
Sezgisel olarak, bunun sanal bir işlev gibi çalışması gerektiğini düşünürdüm. B A'yı genişletirse ve A ve B'nin her ikisi de doStuff adında sanal işlevlere sahipse, derleyici A örneklerinin A.doStuff ve B örneklerinin B.doStuff kullanması gerektiğini bilir. Statik fonksiyonlarla neden aynısını yapamıyor? Sonuçta, derleyici her nesnenin hangi sınıfın bir örneği olduğunu bilir.
Jay

Eee ... Jay, statik bir yöntemin bir örneğe çağrılmasına gerek yok (genellikle değil) ...
meriton

2
meriton, ama sonra daha da kolay, değil mi? Bir sınıf adı kullanılarak statik bir yöntem çağrılırsa, sınıfa uygun yöntemi kullanırsınız.
CPerkins

Ama sonra sizin için yapmayı geçersiz kılan şey. A.doStuff () öğesini çağırırsanız, "B A genişletir" seçeneğinde geçersiz kılınan sürümü veya "C A genişletir" seçeneğinde geçersiz kılınan sürümü kullanın. Ve C veya B'ye sahipseniz, o zaman zaten bu sürümleri çağırıyorsunuz ... geçersiz kılmaya gerek yok.
PSpeed

@meriton: Statik bir yöntemin genellikle bir örnekle çağrılmadığı doğrudur, ancak böyle bir çağrının Java'nın geçerli tasarımı göz önüne alındığında yararlı bir şey yapmadığı varsayılır! Alternatif bir tasarımın daha iyi bir fikir olabileceğini öneriyorum. BTW, çok gerçek anlamda statik fonksiyonlar oldukça rutin olarak bir örnekle çağrılır: Statik fonksiyonu sanal bir fonksiyondan çağırdığınızda. Ardından örtük olarak this.function (), yani geçerli örneği alırsınız.
Jay

5

Geçersiz kılarak, nesne türüne bağlı olarak polimorfik bir doğa oluşturabiliriz. Statik yöntemin nesne ile ilişkisi yoktur. Böylece java statik yöntem geçersiz kılmayı destekleyemez.


5

Jay'in yorumunu beğendim ve ikiye katladım ( https://stackoverflow.com/a/2223803/1517187 ).
Bunun Java'nın kötü tasarımı olduğuna katılıyorum.
Diğer birçok dil, önceki yorumlarda gördüğümüz gibi, statik yöntemlerin geçersiz kılınmasını desteklemektedir. Jay'in benim gibi Delphi'den Java'ya geldiğini hissediyorum.
Delphi (Object Pascal) OOP uygulayan ilk dildi.
Geçmişte ticari GUI ürünleri yazmanın tek dili olduğu için birçok insanın bu dille deneyimi olduğu açıktır. Ve - evet, Delphi'de statik yöntemleri geçersiz kılabiliriz. Aslında, Delphi'deki statik yöntemlere "sınıf yöntemleri" denirken, Delphi'nin "Bağlanma statik yöntemleri" kavramı farklıydı ve bunlar erken bağlanma yöntemiydi. Geç bağlama yöntemlerini geçersiz kılmak için "sanal" yönerge bildirmeniz gerekir. Bu yüzden çok rahat ve sezgisel ve Java bunu beklenebilir.


3

Statik yöntemleri geçersiz kılmak ne işe yarar? Bir örnek üzerinden statik yöntemleri çağıramazsınız.

MyClass.static1()
MySubClass.static1()   // If you overrode, you have to call it through MySubClass anyway.

DÜZENLEME: dil tasarımında talihsiz dikkatsizlik sonucu, o görünür olabilir bir örneği üzerinden statik yöntemleri çağırmak. Genellikle bunu kimse yapmaz. Benim hatam.


8
"Statik yöntemleri bir örnek üzerinden çağıramazsınız" Aslında, Java'nın tuhaflıklarından biri, son derece kötü bir fikir olsa bile, statik örnekleri bir örnek aracılığıyla çağırabilmenizdir.
Powerlord

1
Gerçekten de Java, statik üyelere örnekler aracılığıyla erişilmesine izin verir: bkz . Java'daki statik değişken
Richard JP Le Guen

Doğru bir modern IDE, bunu yaptığınızda bir uyarı oluşturur, bu nedenle en azından Oracle geriye dönük uyumluluk işini devam ettirirken yakalayabilirsiniz.
Gimby

1
Bir örnek üzerinden statik bir yöntemi çağırabilmenin kavramsal olarak yanlış bir yanı yoktur. Bu, kavga uğruna tartışıyor. Neden Date örneği gibi bir şey, örnek veriyi çağrı arabirimi aracılığıyla işleve geçiren kendi statik yöntemlerini ÇAĞIRAMALIDIR?
RichieHH

@RichieHH Bu konuda tartışmayacakları şey bu değil. Soru neden bu çağrıya izin verilir edilir variable.staticMethod()yerine, Class.staticMethod()nerede, variableaçıklanmış türe sahip bir değişkendir Class. Kötü dil tasarımı olduğuna katılıyorum.
balıkçılarKas

3

Java'da geçersiz kılma, belirli yöntemin nesnenin çalışma zamanı türüne göre çağrılması anlamına gelir, derleme zamanı türüne değil (geçersiz kılınmış statik yöntemlerde olduğu gibi). Statik yöntemler sınıf yöntemleri olduğundan, örnek yöntemler değildir, bu nedenle hangi başvurunun hangi Object veya örneğe işaret ettiği gerçeğiyle ilgisi yoktur, çünkü statik yöntemin doğası nedeniyle belirli bir sınıfa aittir. Alt sınıfta yeniden bildirebilirsiniz, ancak alt sınıf, üst sınıfın statik yöntemleri hakkında hiçbir şey bilmeyecektir, çünkü dediğim gibi, yalnızca bildirildiği sınıfa özgüdür. Nesne referanslarını kullanarak onlara erişmek sadece Java tasarımcıları tarafından verilen ekstra bir özgürlüktür ve kesinlikle bu uygulamayı sadece daha fazla ayrıntı ve örnekle kısıtladıklarında durdurmayı düşünmemeliyiz. http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html


3

Geçersiz kılarak dinamik polimorfizm elde edersiniz. Statik yöntemleri geçersiz kılma dediğinizde, kullanmaya çalıştığınız kelimeler çelişkilidir.

Statik diyor - derleme zamanı, geçersiz kılma dinamik polimorfizm için kullanılır. Her ikisi de doğada zıttır ve bu nedenle birlikte kullanılamaz.

Dinamik polimorfik davranış, bir programcı bir nesne kullandığında ve bir örnek yöntemine eriştiğinde ortaya çıkar. JRE, ne tür bir nesne kullandığınıza bağlı olarak farklı sınıfların farklı örnek yöntemlerini eşler.

Statik yöntemleri geçersiz kıldığınızı söylediğinizde, derleme zamanında bağlanacak olan sınıf adını kullanarak erişeceğimiz statik yöntemler olduğundan, çalışma zamanında yöntemleri statik yöntemlerle bağlama kavramı yoktur. Dolayısıyla statik yöntemlerin "geçersiz kılınması" teriminin bir anlamı yoktur.

Not: bir nesneyle bir sınıf yöntemine erişseniz bile, hala java derleyici bunu bulmak için yeterince akıllıdır ve statik bağlantı yapar.


Bu, çalışma zamanında statik yöntemin aslında kapsayıcı sınıfın bir örneğinden çağrıldığı birçok durumda doğru değildir ve bu nedenle işlevin hangi örneklerinin çağrıldığını belirlemek mükemmel şekilde mümkündür.
RichieHH

static derleme zamanı anlamına gelmez, static herhangi bir nesne yerine sınıfa bağlı olduğu anlamına gelir. bir sınıf fabrikası yaratmaktan daha mantıklı olmasa da, statik hariç Box.createBoxdaha mantıklıdır BoxFactory.createBoxve istisnaları atmadan inşaatı kontrol etmek gerektiğinde kaçınılmaz bir modeldir (inşaatçılar başarısız olamaz, sadece işlemi / fırlatmayı öldürebilirler) istisna), bununla birlikte statik bir yöntem hata durumunda null değerini döndürebilir, hatta hastebin.com/codajahati.java gibi bir şey yazmak için başarı / hata geri çağrılarını kabul edebilir .
Dmitry

2

Bu sorunun cevabı basittir, statik olarak işaretlenen yöntem veya değişken yalnızca sınıfa aittir, Bu nedenle bu statik yöntem yalnızca süper sınıfa ait olduğu için alt sınıfta devralınamaz.


1
Merhaba G4uKu3_Gaurav. Katkıda bulunmaya karar verdiğiniz için teşekkür ederiz. Ancak genellikle bundan daha uzun ve daha ayrıntılı cevaplar bekliyoruz.
DJClayworth

@DJClayworth detaylı cevap için bu bağlantıyı takip etmelisiniz geeksforgeeks.org/…
g1ji

Bağlantı için teşekkürler. Aslında, siteye yeni gelenlere yardımcı olmak, sitenin alışkın olmayanlar için nasıl çalıştığını açıklamak için buradayım, soruyu cevaplamam gerektiğinden değil.
DJClayworth

1

Kolay çözüm: Singleton örneğini kullanın. Geçersiz kılmalara ve mirasa izin verir.

Sistemimde, iletilen Class için örnek döndüren SingletonsRegistry sınıfına sahibim. Örnek bulunmazsa oluşturulur.

Haxe dil sınıfı:

package rflib.common.utils;
import haxe.ds.ObjectMap;



class SingletonsRegistry
{
  public static var instances:Map<Class<Dynamic>, Dynamic>;

  static function __init__()
  {
    StaticsInitializer.addCallback(SingletonsRegistry, function()
    {
      instances = null;
    });

  } 

  public static function getInstance(cls:Class<Dynamic>, ?args:Array<Dynamic>)
  {
    if (instances == null) {
      instances = untyped new ObjectMap<Dynamic, Dynamic>();      
    }

    if (!instances.exists(cls)) 
    {
      if (args == null) args = [];
      instances.set(cls, Type.createInstance(cls, args));
    }

    return instances.get(cls);
  }


  public static function validate(inst:Dynamic, cls:Class<Dynamic>)
  {
    if (instances == null) return;

    var inst2 = instances[cls];
    if (inst2 != null && inst != inst2) throw "Can\'t create multiple instances of " + Type.getClassName(cls) + " - it's singleton!";
  }

}

Çok güzel, Haxe programlama dilini ilk kez duydum :)
cyc115

1
Bu, Java'da sınıfın kendisinde statik bir yöntem olarak çok daha iyi uygulanır; Singleton.get(). Kayıt defteri sadece kaynatma tavanıdır ve sınıflarda GC'yi engeller.
Lawrence Dol

Haklısın, klasik bir çözüm. Neden kayıt defterini seçtiğimi tam olarak hatırlamıyorum, muhtemelen bu sonuca yol açan bir düşünce çerçevesi vardı.
Raivo Fishmeister

1

Statik bir yöntem, değişken, blok veya iç içe sınıf , bir nesne yerine tüm sınıfa aittir .

Java'da Yöntem, bir Nesnenin / Sınıfın davranışını ortaya çıkarmak için kullanılır. Burada, yöntem statik olduğu için (yani, sadece bir sınıfın davranışını temsil etmek için statik yöntem kullanılır.) Tüm sınıfın davranışını değiştirmek / geçersiz kılmak , Nesne yönelimli programlamanın temel sütunlarından birinin olgusunu, yani yüksek bütünlüğü ihlal eder. . (bir kurucunun Java'da özel bir yöntem olduğunu unutmayın.)

Yüksek Uyum - Bir sınıfın yalnızca bir rolü olmalıdır. Örneğin: Bir otomobil sınıfı, bisiklet, kamyonlar, uçaklar vb. Değil yalnızca otomobil nesneleri üretmelidir. Ancak Car sınıfı, yalnızca kendisine ait bazı özelliklere (davranış) sahip olabilir.

Bu nedenle, java programlama dilini tasarlarken. Dil tasarımcıları, geliştiricilerin yalnızca bir yöntemi doğada statik hale getirerek bir sınıfın bazı davranışlarını kendi başına tutmasına izin vermeyi düşündüler.


Parçalı kod denemesi altında statik yöntemini geçersiz kılmak için, ancak değil herhangi derleme hatayla karşılaşabilirsiniz.

public class Vehicle {
static int VIN;

public static int getVehileNumber() {
    return VIN;
}}

class Car extends Vehicle {
static int carNumber;

public static int getVehileNumber() {
    return carNumber;
}}

Bunun nedeni, burada bir yöntemi geçersiz kılmıyoruz, ancak sadece yeniden beyan ediyoruz. Java, bir yöntemin (statik / statik olmayan) yeniden bildirilmesine izin verir.

Statik anahtar kelimenin Car sınıfının getVehileNumber () yönteminden kaldırılması derleme hatasına neden olur. Çünkü, yalnızca Vehicle sınıfına ait statik yöntemin işlevselliğini değiştirmeye çalışıyoruz .

Ayrıca, getVehileNumber () son olarak bildirilirse , kod derlenmez, çünkü nihai anahtar kelime programcının yöntemi yeniden bildirmesini kısıtlar.

public static final int getVehileNumber() {
return VIN;     }

Genel olarak, bu statik yöntemlerin nerede kullanılacağı için yazılım tasarımcıları kadar. Ben şahsen herhangi bir sınıf örneği oluşturmadan bazı eylemleri gerçekleştirmek için statik yöntemleri kullanmayı tercih ederim. İkincisi, bir sınıfın davranışını dış dünyadan gizlemek.


1

İşte basit bir açıklama. Statik bir yöntem bir sınıfla ilişkilendirilirken, bir örnek yöntemi belirli bir nesneyle ilişkilendirilir. Geçersiz kılmalar, belirli bir nesneyle ilişkili geçersiz kılınmış yöntemlerin farklı uygulamalarının çağrılmasına izin verir. Bu nedenle, nesnelerle bile ilişkili olmayan, ancak sınıfın kendisinde ilk etapta statik yöntemi geçersiz kılmak tersine sezgiseldir. Statik yöntemler, hangi nesnenin çağırdığını temel alarak geçersiz kılınamaz, her zaman oluşturulduğu sınıfla ilişkilendirilir.


public abstract IBox createBox();İç IBox arayüzüne sahip olmak nasıl sezgiseldir ? Box, createBox'ı geçersiz kılmak için IBox'ı uygulayabilir ve nesne oluşturmanın geçerli bir IBox ile sonuçlanmasını sağlayabilir, aksi takdirde null değerini döndürür. Yapıcılar "null" döndüremezler ve bu nedenle (1) HER YERDE (şimdi ne yapıyoruz) istisnalar kullanmaya veya (2) daha önce söylediğim şeyi yapan, ancak acemilere veya uzmanlara mantıklı olmayan bir şekilde fabrika sınıfları oluşturmaya zorlanırsınız. Java (şimdi de yapıyoruz). Statik uygulanmayan yöntemler bunu çözer.
Dmitry

-1

Şimdi yukarıdaki cevapları görmek, herkes statik yöntemleri geçersiz kılamayacağımızı bilir, ancak statik sınıflara alt sınıftan erişme kavramı hakkında yanlış anlaşılmamalıdır .

Bu statik yöntem alt sınıfta tanımlanan yeni statik yöntemle gizlenmemişse, alt sınıf başvurusu ile süper sınıf statik yöntemlerine erişebiliriz.

Örneğin, aşağıdaki koda bakın: -

public class StaticMethodsHiding {
    public static void main(String[] args) {
        SubClass.hello();
    }
}


class SuperClass {
    static void hello(){
        System.out.println("SuperClass saying Hello");
    }
}


class SubClass extends SuperClass {
    // static void hello() {
    // System.out.println("SubClass Hello");
    // }
}

Çıktı:-

SuperClass saying Hello

Java oracle belgeleri konusuna bakın ve alt sınıftaki statik yöntemlerin gizlenmesi hakkında ayrıntılar için bir Alt Sınıfta Yapabilecekleriniz'i arayın .

Teşekkürler


-3

Aşağıdaki kod mümkün olduğunu gösterir:

class OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriden Meth");   
}   

}   

public class OverrideStaticMeth extends OverridenStaticMeth {   

static void printValue() {   
System.out.println("Overriding Meth");   
}   

public static void main(String[] args) {   
OverridenStaticMeth osm = new OverrideStaticMeth();   
osm.printValue();   

System.out.println("now, from main");
printValue();

}   

} 

1
Hayır değil; statik bildirilmiş bir tür osmolduğu OverridenStaticMethdeğil OverrideStaticMeth.
Lawrence Dol

2
Ayrıca, <big grin> 'i programlarken Meth kullanmaktan kaçınmaya çalışacağım;
Lawrence Dol
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.