Statik yöntemler Java'da miras alınır?


143

Khalid Mughal tarafından Java ™ SCJP Sertifikasyonu için Programcı Kılavuzu okuyordum .

Kalıtım bölümünde,

Üyelerin mirasları beyanedildikleri erişilebilirlikle yakından ilişkilidir. Bir üst sınıf üyesine alt sınıftaki basit adıyla erişilebiliyorsa (süper gibi herhangi bir sözdizimi kullanılmadan), o üye devralınmış olarak kabul edilir

Ayrıca statik yöntemlerin kalıtsal olmadığından bahseder. Ancak aşağıdaki kod gayet iyi:

class A
{
    public static void display()
    {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A
{
    public void show()
    {
        // This works - accessing display() by its simple name -
        // meaning it is inherited according to the book.
        display();
    }
}

display()Sınıfta doğrudan nasıl kullanabilirim B? Dahası, B.display()aynı zamanda çalışıyor.

Kitabın açıklaması sadece örnek yöntemler için mi geçerli?



Benim kopyamda böyle yazmıyor, 1. baskı. Lütfen gerçek bir fiyat teklifi verin.
Lorne Marquis

Yanıtlar:


180

Erişilebilir tüm yöntemler alt sınıflar tarafından miras alınır.

Sun Java Dersleri'nden :

Bir alt sınıf, alt sınıfın hangi pakette olursa olsun, tüm ortak ve korumalı üyelerini devralır. Alt sınıf, üst öğesiyle aynı pakette bulunuyorsa, üst öğenin paket özel üyelerini de devralır. Devralınan üyeleri olduğu gibi kullanabilir, değiştirebilir, gizleyebilir veya yeni üyelerle tamamlayabilirsiniz

Devralınan statik (sınıf) yöntemlerle ve devralınan statik olmayan (örnek) yöntemlerle tek fark, aynı imzayla yeni bir statik yöntem yazdığınızda, eski statik yöntemin geçersiz kılınması değil, gizlenmesidir.

Gönderen sayfa geçersiz kılma ve gizleme arasındaki fark üzerinde.

Saklanma ve geçersiz kılma arasındaki ayrımın önemli sonuçları vardır. Çağrılan geçersiz kılınan yöntemin sürümü, alt sınıftaki sürümdür. Çağıran gizli yöntemin sürümü, üst sınıftan mı yoksa alt sınıftan mı çağrıldığına bağlıdır.


miras alınan, alt sınıfta o üyeyi geçersiz kılabilecek miyiz?
Algoritma

Bu kalıtımın bir parçası, ama hepsi değil. Kalıtımın diğer önemli kısımlarının kodun yeniden kullanımı ve polimorfizm olduğunu söyleyebilirim.
yincrash

Yeniden tanımlamanın geçersiz kılma gibi bazı kuralları da var mı?
Surender Thakran

2
@Algorithmist tam olarak değil. Alt sınıfınızın hiyerarşide daha fazla gördüğü her şey, sınıfınızın miras aldığı şeylerdir. Ancak devralınan statik yöntemler geçersiz kılınamaz, sadece gizlenir (aynı imzayla "yeniden belirtilir"). Bu nedenle, statik yöntemlerinizi nihai olarak da bildirebilirsiniz, önemli değil. Derleme sırasında hangi statik yöntemin çağrılacağı bilinir. Nihai olmayan örnek yöntemlerinde, çözünürlük geçersiz kılınabileceğinden çalışma zamanına ertelenmelidir.
Martin Andersson

1
Son paragrafınız tamamen zarar görmüştür !!! "Geçersiz kılınan geçersiz kılma yönteminin sürümü alt sınıftaki sürümdür" bu doğru değildir: Diyelim ki: Geçersiz kılınan geçersiz kılma yönteminin sürümü, çalışma zamanında yalnızca nesnenin yaptığı JVM tarafından belirlenir. Ara :)
mounaim

14

Kitabın gerçekten söylediği buysa, bu yanlıştır. [1]

Java Dil Şartname # 8.4.8 devletler:

8.4.8 Kalıtım, Geçersiz Kılma ve Gizleme

C sınıfı, doğrudan üst sınıfından aşağıdakilerin hepsinin doğru olduğu tüm üst sınıf m (hem statik hem de örnek) somut yöntemlerini miras alır:

  • m, C'nin doğrudan üst sınıfının bir üyesidir.

  • m, C ile aynı pakette herkese açık, korumalı veya paket erişimi ile beyan edilmiş.

  • C'de bildirilen hiçbir yöntemin m imzasının bir alt imzası (§8.4.2) olan bir imzası yoktur.

[1] Benim kopyamda, 1. baskıda, 2000.


13

Kodunuz üzerinde biraz değişiklik yapan aşağıdaki koddaki farkı yaşayabilirsiniz.

class A {
    public static void display() {
        System.out.println("Inside static method of superclass");
    }
}

class B extends A {
    public void show() {
        display();
    }

    public static void display() {
        System.out.println("Inside static method of this class");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // prints: Inside static method of this class
        b.display();

        A a = new B();
        // prints: Inside static method of superclass
        a.display();
    }
}

Bunun nedeni, statik yöntemlerin sınıf yöntemleridir.

A.display () ve B.display (), ilgili sınıflarının yöntemini çağırır.


1
Çalışmaya çalıştığınız gibi bir örnekte statik bir yöntem çağırmak, Java'da çalışmaz.
Lucas C. Feijo

Bu programın açıkladığı gibi, B'nin nesnesini başlatmak ve mirasın işe yaramasını beklemek statik üyelerle mümkün olmayacaktır. Tutulma / herhangi bir ide içinde aynı kodu almayı deneyin veya javac kullanarak derleyin ve çalıştırın
Gaurav

2
@ LucasC.Feijo aslında işe yarıyor. En azından IDE'mde (tutulma). Sadece bir uyarı alıyorum. Yine de iyi bir tarz olmayabilir ... ama bu farklı bir hikaye.
dingalapadum

2
@ LucasC.Feijo çağrısı bir örnek üzerinde statik bir yöntem önerilmez. Ancak, sınıf adında statik bir yöntem çağırmakla aynı şekilde çalışır.
Ziyang Zhang

5

B.display () işlevi, statik bildirim yöntemi / üyeyi sınıfa ait yapar ve herhangi bir sınıf örneğini (Object olarak adlandırmaz) çalıştırdığı için çalışır. Burada daha fazla bilgi edinebilirsiniz .

Dikkat edilmesi gereken başka bir şey, statik bir yöntemi geçersiz kılamamanızdır, alt sınıfınızın aynı imzayla statik bir yöntem bildirmesini sağlayabilirsiniz, ancak davranışı beklediğinizden farklı olabilir. Muhtemelen miras olarak kabul edilmemesinin nedeni budur. Sorunlu senaryoya ve açıklamaya buradan göz atabilirsiniz .


4

Java'daki statik yöntemler devralınır, ancak geçersiz kılınamaz. Aynı yöntemi bir alt sınıfta bildirirseniz, üst sınıf yöntemini geçersiz kılmak yerine gizlersiniz. Statik yöntemler polimorfik değildir. Derleme zamanında statik yöntem statik olarak bağlanır.

Misal:

public class Writer {
    public static void write() {
        System.out.println("Writing");
    }
}

public class Author extends Writer {
    public static void write() {
        System.out.println("Writing book");
    }
}

public class Programmer extends Writer {

    public static void write() {
        System.out.println("Writing code");
    }

    public static void main(String[] args) {
        Writer w = new Programmer();
        w.write();

        Writer secondWriter = new Author();
        secondWriter.write();

        Writer thirdWriter = null;
        thirdWriter.write();

        Author firstAuthor = new Author();
        firstAuthor.write();
    }
}

Aşağıdakileri alacaksınız:

Writing
Writing
Writing
Writing book

2

Statik yöntemler Java'da kalıtsaldır, ancak polimorfizmde yer almazlar. Statik yöntemleri geçersiz kılmaya çalışırsak, üst sınıf statik yöntemleri geçersiz kılmak yerine gizlerler.


Bu cevabı küçümsemek için bir neden göremiyorum. En azından ilk kısım, net ve net. İkinci kısım teknik olarak çok fazla alınmamalıdır, aksi takdirde sorun olmaz. Açıklığa kavuşturmak için, geçersiz kılma yöntemlerinde döndürme türü değişebilir (alt türe), oysa statik yöntemlerde durum böyle değildir. Teknik olarak 'geçersiz kılma girişimi' statik yöntemler için geçerli değildir, bu yüzden söyleyebileceğimiz tek şey yapamayız.
sharhp

2

Bu konsept göründüğü kadar kolay değil. Hasa ilişkisi olan kalıtım olmadan statik üyelere erişebiliriz. Ebeveyn sınıfını da genişleterek statik üyelere erişebiliriz. Bu bir ISA ilişkisi (Miras) olduğu anlamına gelmez. Aslında statik üyeler sınıfa aittir ve statik bir erişim değiştiricisi değildir. Erişim değiştiriciler statik üyelere erişime izin verdiği müddetçe, onları diğer sınıflarda kullanabiliriz. Herkese açık olduğu gibi, aynı paketin içinde ve paketin dışında da erişilebilir olacaktır. Özel için hiçbir yerde kullanamayız. Varsayılan olarak, yalnızca paket içinde kullanabiliriz. Ancak korumalılar için süper sınıfı genişletmeliyiz. Yani statik yöntemi diğer sınıfa almak Statik olmaya bağlı değildir. Erişim değiştiricilerine bağlıdır. Bence, Statik üyeler, erişim değiştiricileri izin veriyorsa erişebilir. Aksi takdirde Hasa ilişkisinde kullandığımız gibi kullanabiliriz. Ve bir ilişkisi var miras değil. Yine statik yöntemi geçersiz kılamayız. Başka bir yöntem kullanabilir, ancak bunu geçersiz kılamazsak, HasA ilişkisidir. Onları geçersiz kılamazsak miras olmayacak, böylece yazar% 100 doğruydu.


Üst sınıfını genişletme olduğu bir 'is-a' ilişkisi. Erişim özelse sınıf içinden kullanabilirsiniz. 'korumalı', geçerli paketteki türetilmiş sınıfları ve sınıfları içerir. Burada çok fazla hata var.
Lorne Marquis

0

Statik yöntem alt sınıfta kalıtsaldır, ancak polimorfizm değildir. Statik yöntemin uygulanmasını yazarken, üst öğenin sınıf yöntemi geçersiz kılınır, gizlenir. Düşünün ki, kalıtsal değilse, o olmadan classname.staticMethodname();nasıl erişebilirsiniz ?


0

Tüm ortak ve korunan üyeler herhangi bir sınıftan miras alınabilirken, varsayılan veya paket üyeler de üst sınıfınkiyle aynı paket içindeki sınıftan miras alınabilir. Statik olup olmadığına bağlı değildir.

Ancak statik üye fonksiyonunun dinamik bağlamada yer almadığı da doğrudur. Bu statik yöntemin imzası hem ebeveyn hem de alt sınıfta aynıysa, çok biçimlilik değil Gölgeleme kavramı uygulanır.


0

Statik yöntemleri geçersiz kılabilirsiniz, ancak polimorfizmi kullanmaya çalışırsanız, sınıf kapsamına göre çalışırlar (Normalde beklediğimizden farklı olarak).

public class A {

    public static void display(){
        System.out.println("in static method of A");
    }
}

public class B extends A {

    void show(){
        display();
    }

     public static void display(){
        System.out.println("in static method of B");
    }

}
public class Test {

    public static void main(String[] args){
        B obj =new B();
        obj.show();

        A a_obj=new B();
        a_obj.display();


    }


}

İlk durumda, o / p "B statik yönteminde" # başarılı geçersiz kılma 2. durumda, o / p "A statik yönteminde" # Statik yöntem - polimorfizmi dikkate almayacaktır


-1

Alt sınıfta aynı imzayla statik yöntemler bildirebiliriz, ancak herhangi bir çalışma zamanı polimorfizmi olmayacağı için geçersiz kılma olarak kabul edilmez. zaman (çalışma zamanında geçersiz kılma) Bu nedenle cevap 'Hayır'dır.


2
İnsanların neden her zaman aşağı oy kullandıklarını ve aşağı oylama nedenini bilmediklerini bilmiyorum.
surajs1n

Bu cevap geçersiz kılmakla ilgilidir. Soru kalıtımla ilgili.
Lorne Marquis

-1

Birçoğu cevaplarını kelimelerle dile getirdi. Bu, kodlarda genişletilmiş bir açıklamadır:

public class A {
    public static void test() {
        System.out.println("A");
    }
    public static void test2() {
        System.out.println("Test");
    }
}

public class B extends A {
    public static void test() {
        System.out.println("B");
    }
}

// Called statically
A.test();
B.test();
System.out.println();

// Called statically, testing static inheritance
A.test2();
B.test2();
System.out.println();

// Called via instance object
A a = new A();
B b = new B();
a.test();
b.test();
System.out.println();

// Testing inheritance via instance call
a.test2();
b.test2();
System.out.println();

// Testing whether calling static method via instance object is dependent on compile or runtime type
((A) b).hi();
System.out.println();

// Testing whether null instance works
A nullObj = null;
nullObj.hi();

Sonuçlar:

A
B

Test
Test

A
B

Test
Test

A

A

Bu nedenle, sonuç budur:

  1. Statiği statik yöntemle. Olarak çağırdığımızda, o sınıfta tanımlanan statik veya miras zincirindekine en yakın sınıfı arayacaktır. Bu, statik yöntemlerin kalıtsal olduğunu kanıtlar.
  2. Bir örnekten statik yöntem çağrıldığında, derleme zamanı türünde tanımlanan statik yöntemi çağırır.
  3. Statik yöntem bir nullörnekten çağrılabilir . Benim tahminim derleyici değişken derleme sırasında sınıf bulmak ve bunu uygun statik yöntem çağrısı çevirmek kullanacaktır.

1
Sadece kod bir açıklama değil, bir gösteri. Bu soruya verilen bir cevapta, sadece bazı belirtilmemiş uygulamaların davranışlarını göstermekle kalmayıp, normatif referanslar belirtilmelidir.
Lorne Marquis

-2

Statik üyeler evrensel üyelerdir. Bunlara her yerden erişilebilir.


4
kelimenin tam anlamıyla alınan herhangi bir yerden erişilebilir , bu yanlış: statik! = kapsam. açıklamak isteyebilirsiniz :-)
kleopatra

Aslında, bu cevap tam anlamıyla alındığında iyidir. Kod tek bir yerde sınıfın statik bir üyesi erişemez gidebilirsiniz tek bir yer düşünemiyorum. Bunlara, statik sınıf başlatıcılarda, statik yapıcılarda, örnek yapıcılarında, yöntemlerde, özelliklerde, farklı sınıflarda, herhangi bir kapsamda erişebilirsiniz. Sınıf ve statik yöntem herkese açık olduğu sürece, statik başlatıcılarda dairesel bir bağımlılık olmadığı varsayılarak her yerden erişilebilir. Özünde, statik üyeler kalıtsal değildir, sadece her yerden erişilebilen sınıf düzeyinde (yani evrensel) yöntemlerdir.
Triynko

@Triynko Özel veya paket korumalı paketin dışından erişilen yöntemlerde yanıt yanlıştır.
Lorne Marquis

@kleopatra - konu dışı. java salıncak? insanlar bunu bugünlerde kullanıyor mu?
MasterJoe

@Pavan sınıfın dışından özel statik çağırmayı deneyin. Çalışmaz.
Rakesh Yadav

-2

Statik üyeler alt sınıfa devralınmayacak çünkü kalıtım yalnızca statik olmayan üyeler içindir. Ve statik üyeler statik yükleyici içinde sınıf yükleyicisi tarafından yüklenecektir. Kalıtım yalnızca nesnenin içine yüklenen üyeler içindir


Tamamen yanlış. Bkz. JLS # 8.4.8 .
Lorne Marquis
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.