Geçersiz Kılma ve Java'yı Gizleme - Kafası Karışık


88

Java'da saklanmaktan geçersiz kılmanın ne kadar farklı olduğu konusunda kafam karıştı. Bunların nasıl farklılaştığı konusunda daha fazla ayrıntı verebilir mi? Java Eğitimi'ni okudum ama örnek kod hala kafamı karıştırdı.

Daha açık olmak gerekirse, geçersiz kılmayı iyi anlıyorum. Benim sorunum, birinin örnek düzeyinde, diğerinin sınıf düzeyinde olması dışında, gizlemenin ne kadar farklı olduğunu görmüyorum.

Java eğitim koduna bakın:

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

Sonra bir alt sınıfımız var Cat:

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method" + " in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method" + " in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

Sonra derler:

Bu programın çıktısı aşağıdaki gibidir:

Hayvanda sınıf yöntemi.

Cat'deki örnek yöntemi.

Bana göre, bir sınıf yöntemini testClassMethod()doğrudan sınıftan çağırmanın sınıftaki yöntemi Animalyürüttüğü Animaloldukça açık, burada özel bir şey yok. Daha sonra testInstanceMethod()from a referansı çağırırlar myCat, bu yüzden o zaman yürütülen yöntemin örneğindeki yöntem olduğu oldukça açık Cat.

Gördüğüm kadarıyla, aramayı gizleme, geçersiz kılma gibi davranıyor, öyleyse neden bu ayrımı yapalım? Bu kodu yukarıdaki sınıfları kullanarak çalıştırırsam:

Cat.testClassMethod();

Alacağım: Cat'deki sınıf yöntemi. Ama eğer Cat'i kaldırırsam şunu testClassMethod()elde ederim: Animal'daki sınıf metodu.

Bu da bana, bir alt sınıfa, üst sınıfta olduğu gibi aynı imzaya sahip statik bir yöntem yazmanın, geçersiz kılma anlamına geldiğini gösteriyor.

Umarım nerede kafamın karıştığını netleştiriyorum ve birileri biraz ışık tutabilir. Şimdiden çok teşekkürler!


Yanıtlar:


103

Geçersiz kılma temelde geç bağlanmayı destekler. Bu nedenle, hangi yöntemin çağrılacağına çalışma zamanında karar verilir. Statik olmayan yöntemler içindir.

Gizleme, diğer tüm üyeler içindir (statik yöntemler, örnek üyeleri, statik üyeler). Erken bağlanmaya dayanır. Daha açık bir ifadeyle, çağrılacak veya kullanılacak yöntem veya üye derleme sırasında kararlaştırılır.

Örneğinizde, ilk çağrı Animal.testClassMethod()bir staticyönteme yapılan çağrıdır , bu nedenle hangi yöntemin çağrılacağı oldukça emindir.

İkinci çağrıda, myAnimal.testInstanceMethod()statik olmayan bir yöntemi çağırırsınız. Bu, çalışma zamanı polimorfizmi dediğin şeydir. Hangi yöntemin çağrılacağına çalışma zamanına kadar karar verilmez.

Daha fazla açıklama için okuyun Geçersiz Kılma Vs Gizleme'yi .


3
Hızlı cevap için teşekkürler, bu durumu açıklığa kavuşturuyor! JavaRanch örneğinde, sınıfı doğrudan kullanmak yerine değişkeni sınıf yöntemini çağırmak için kullandıklarını fark ettim, bu da anlaşılmasını kolaylaştırıyor. Java öğreticisinde sınıfı doğrudan kullandıklarını sanıyorum çünkü statik bir yöntemi çağırmak için bir örnek kullanmak muhtemelen iyi bir uygulama değildir, ancak Animal.testClassMethod () yerine myAnimal.testClassMethod () kullanmalıydılar .
Lostlinkpr

Örnek olarak değil, doğru bir şekilde kelimelere dökebildiğiniz için +1! :)
WhyNotHugo

@Kazekage Gaara Aşırı yükleme ve gizleme arasında fark var mı?
gstackoverflow

1
Tabii ki yanıta katılıyorum, peki ya private methods? Onlar olamaz overriddenalt sınıf varlıklarından haberdar olmadığı için Dolayısıyla onlar olabilir .. hiddenyerine.
Paschalis

Mükemmel Cevap! Yine de eksiksizlik adına coderanch'daki örneği ekleyebilirsiniz :)
Shubham Mittal

19

Statik yöntemler gizlidir, statik olmayan yöntemler geçersiz kılınır. Çağrılar "bir şey ()" ile "this.something ()" arasında nitelikli olmadığında fark dikkat çekicidir.

Bunu kelimelere dökecek gibi görünemiyorum, bu yüzden işte bir örnek:

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

ÇIKTI:

animal.something
dog.eat

1
tamam, öyleyse `` köpek husky = yeni köpek () '' olarak adlandırırsam ne olur? ve husky.Animal();ona hayvan yazacakdiyecekler. bir şey mi yoksa köpek mi? ** Bunu söylemek YANLIŞ
amarnath harish

@amarnathharish Yapamazsınız .Animal(), unutmayın Animal()bir yapıcıdır.
Dude156

Ve merak eden herkes için daha fazla açıklama olarak something(), Animal() her zaman in Animal's çağrısının nedeni, something()statik bir yönteme yapılan çağrının çalışma zamanı yerine derleme zamanında çözülmesidir. Bu, statik yöntem çağrısının Animal()her zaman örtük olarak çağırdığı anlamına gelir Animal.something(). Düşünürseniz, bu oldukça sezgiseldir: statik bir yönteme className.staticMethodName()yapılan bir çağrı, çağrı aynı sınıfta değilse, bir sınıf adıyla (yani ) önce gelmelidir .
Dude156

14

Bu, geçersiz kılmalar ve gizleme arasındaki farktır.

  1. Hem ana sınıf hem de alt sınıftaki yöntem bir örnek yöntemse, buna geçersiz kılmalar denir.
  2. Hem ana sınıf hem de alt sınıftaki yöntem statik yöntemse, buna hiding denir.
  3. Bir yöntem, üstte ve alt öğede bir örnek olarak statik olamaz. ve tersi.

görüntü açıklamasını buraya girin


3
O tabloyu doğrudan OP'nin anlamasına yardımcı olmadığını söylediği eğitimden kesip yapıştırdınız.
wolfcastle

Tablo çok net bir şekilde ortaya koymaktadır, örneklerde tüm durumlar dikkate alınmamıştır.
tutak

3

Sorunuzu doğru anlarsam, cevap "zaten geçersiz kılıyorsunuz" olacaktır.

"Bu da bana, bir alt sınıfa üst sınıfta olduğu gibi aynı ada sahip statik bir yöntem yazmanın geçersiz kılma anlamına geldiğini gösteriyor."

Bir alt sınıfa, bir üst sınıftaki bir yöntemle tam olarak aynı ada sahip bir yöntem yazarsanız, bu, üst sınıfın yöntemini geçersiz kılar. @Override açıklamasının bir yöntemi geçersiz kılmak için gerekli değildir. Bununla birlikte, kodunuzu daha okunabilir hale getirir ve derleyiciyi bir yöntemi gerçekten geçersiz kıldığınızı kontrol etmeye zorlar (ve örneğin, alt sınıf yöntemini yanlış yazmadı).


1
Bu cevap, geçersiz kılma / gizleme ile ilgili olarak örnek ve statik yöntemleri ele almakta başarısız olur.
Paul Bellora

3

Geçersiz kılma, yalnızca örnek yöntemleriyle gerçekleşir. Referans değişkenin türü Animal ve nesne Cat olduğunda, örnek yöntemi Cat'ten çağrılır (bu geçersiz kılar). Aynı acat nesnesi için Animal sınıf metodu kullanılır.

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

Çıktı:

The instance method in Cat.
Class method in Animal.

2
public class First {

    public void Overriding(int i) {  /* will be overridden in class Second */ }

    public static void Hiding(int i) {  /* will be hidden in class Second
                                           because it's static */ }
}


public class Second extends First {

    public void Overriding(int i) {  /* overridden here */  }

    public static void Hiding(int i) {  /* hides method in class First
                                           because it's static */ } 
}

Ezberlemenin kuralı basittir: Genişleyen bir sınıftaki bir yöntem durağı void olarak değiştiremez ve void'i statik olarak değiştiremez. Derleme hatasına neden olacaktır.

Ama eğer void Namedeğiştirilirsevoid Name Geçersiz kılınır.

Ve eğer static Namedeğiştirilirse, static NameGizleniyor. (Hem alt sınıfın statik yöntemi hem de üst sınıfın biri, yöntemi çağırmak için kullanılan referansın türüne bağlı olarak çağrılabilir.)


1

Bu kod parçacığında, gizleme yöntemleri ile geçersiz kılma yöntemleri arasındaki farkı göstermek için 'statik' yerine 'özel' erişim değiştiricisini kullanıyorum.

class Animal {
// Use 'static' or 'private' access modifiers to see how method hiding work.
private void testInstancePrivateMethod(String source) {
    System.out.println("\tAnimal: instance Private method calling from "+source);
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Private method.");
    testInstancePrivateMethod( Animal.class.getSimpleName() );
}

// Use default, 'protected' or 'public' access modifiers to see  how method overriding work.
protected void testInstanceProtectedMethod(String source) {
    System.out.println("\tAnimal: instance Protected method calling from "+source);
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Protected method.");
    testInstanceProtectedMethod( Animal.class.getSimpleName() );
  } 
}  


public class Cat extends Animal {
private void testInstancePrivateMethod(String source) {
    System.out.println("Cat: instance Private method calling from " + source );
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("Cat: instance Public method with using of Private method.");
    testInstancePrivateMethod( Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingPrivateMethodInside();
}

protected void testInstanceProtectedMethod(String source) {
    System.out.println("Cat: instance Protected method calling from "+ source );
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("Cat: instance Public method with using of Protected method.");
    testInstanceProtectedMethod(Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingProtectedMethodInside();
}

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("----- Method hiding -------");
    myCat.testInstanceMethodUsingPrivateMethodInside();
    System.out.println("\n----- Method overriding -------");
    myCat.testInstanceMethodUsingProtectedMethodInside();
}
}

Çıktı:

----- Method hiding -------
Cat: instance Public method with using of Private method.
Cat: instance Private method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Private method.
   Animal: instance Private method calling from Animal

----- Method overriding -------
Cat: instance Public method with using of Protected method.
Cat: instance Protected method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Protected method.
Cat: instance Protected method calling from Animal

neden olumlu oylar almadığını merak ediyorum ... çok takdir edilen cevap.
amarnath harish

0

Son Java çalışmalarıma göre

  • alt sınıf, alt sınıfta aynı imzayla aynı yönteme sahip olduğunda yöntemi geçersiz kılar.
  • Alt sınıf aynı yöntem adına ancak farklı parametrelere sahip olduğunda yöntem gizleme . Bu durumda, ana yöntemi geçersiz kılmıyorsunuz, aksine saklıyorsunuz.

OCP Java 7 kitabından örnek, sayfa 70-71:

public class Point {
  private int xPos, yPos;
  public Point(int x, int y) {
        xPos = x;
        yPos = y;
  }

  public boolean equals(Point other){
  .... sexy code here ...... 
  }

  public static void main(String []args) {
   Point p1 = new Point(10, 20);
   Point p2 = new Point(50, 100);
   Point p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //point's class equals method get invoked
  }
}

ama şu ana yazarsak:

  public static void main(String []args) {
   Object p1 = new Point(10, 20);
   Object p2 = new Point(50, 100);
   Object p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //Object's class equals method get invoked
  }

İkinci ana bölümde, Object sınıfını statik tip olarak kullanıyoruz, bu yüzden Point nesnesinde eşit yöntemi çağırdığımızda, parametre olarak bir Point sınıfının gelmesini bekliyor, ancak Object geliyor. Yani Object sınıfı eşittir yöntemi çalıştırılıyor, çünkü orada bir eşittir (Object o) var. Bu durumda, Point'in sınıfı eşittir geçersiz kılınmaz, ancak Object sınıfı eşittir yöntemini gizler .


0
public class Parent {

  public static void show(){
    System.out.println("Parent");
  }
}

public class Child extends Parent{

  public static void show(){
    System.out.println("Child");
  }
}

public class Main {

public static void main(String[] args) {
    Parent parent=new Child();
    parent.show(); // it will call parent show method
  }
}

// We can call static method by reference ( as shown above) or by using class name (Parent.show())

0

Bağlantılı Java eğitim sayfası, geçersiz kılma ve gizleme kavramını açıklar

Üst sınıftaki örnek yöntemi olarak aynı imzaya (ad, artı sayı ve parametrelerinin türü) ve dönüş türüne sahip bir alt sınıftaki örnek yöntemi, üst sınıfın yöntemini geçersiz kılar.

Bir alt sınıf, üst sınıftaki statik bir yöntemle aynı imzaya sahip statik bir yöntemi tanımlıyorsa, alt sınıftaki yöntem üst sınıftaki yöntemi gizler.

Statik bir yöntemi gizlemekle bir örnek yöntemini geçersiz kılmak arasındaki ayrımın önemli çıkarımları vardır:

  1. Geçersiz kılınan örnek yönteminin çağrılan sürümü, alt sınıftaki olandır.
  2. Çağrılan gizli statik yöntemin sürümü , üst sınıftan mı yoksa alt sınıftan mı çağrıldığına bağlıdır.

Örneğinize geri dönersek:

Animal myAnimal = myCat;

 /* invokes static method on Animal, expected. */
 Animal.testClassMethod(); 

 /* invokes child class instance method (non-static - it's overriding) */
 myAnimal.testInstanceMethod();

Yukarıdaki ifade henüz gizlenmeyi göstermiyor.

Şimdi farklı çıktı elde etmek için kodu aşağıdaki gibi değiştirin:

  Animal myAnimal = myCat;
  
  /* Even though myAnimal is Cat, Animal class method is invoked instead of Cat method*/
  myAnimal.testClassMethod();
  
  /* invokes child class instance method (non-static - it's overriding) */
  myAnimal.testInstanceMethod();

Kendini gizlemenin ne anlama geldiğini anlamaya çalışıyorum. Ne saklamak nedir? Parent sınıfındaki statik yöntem, çağrıldığı için (en az beklenen) gizli mi? Veya Child sınıfındaki statik yöntem, çağrılmadığı için gizli mi?
scorpion

0

Yukarıda listelenen örneklere ek olarak, gizleme ve geçersiz kılma arasındaki farkı açıklığa kavuşturmak için küçük bir örnek kod aşağıda verilmiştir:

public class Parent {

    // to be hidden (static)
    public static String toBeHidden() {
        return "Parent";
    }

    // to be overridden (non-static)
    public String toBeOverridden() {
        return "Parent";
    }

    public void printParent() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Child extends Parent {

    public static String toBeHidden() {
        return "Child";
    }

    public String toBeOverridden() {
        return "Child";
    }

    public void printChild() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        child.printParent();
        child.printChild();
    }
}

Çağrısı child.printParent()Çıktıların :
gizlenecek: Ana
geçersiz kılınmış olması: Çocuk

Çağrısı child.printChild() çıkışları:
gizlenmesine: Çocuk
geçersiz kılınmış olması: Çocuk

Yukarıdaki çıktılardan da görebileceğimiz gibi (özellikle kalın işaretli çıktılar), yöntem gizleme, geçersiz kılmadan farklı davranır.

Java, yalnızca yöntemler için hem gizlemeye hem de geçersiz kılmaya izin verir. Aynı kural değişkenler için geçerli değildir. Değişkenlerin geçersiz kılınmasına izin verilmez, bu nedenle değişkenler yalnızca gizlenebilir (statik veya statik olmayan değişken arasında fark yoktur). Aşağıdaki örnek, yöntemin nasıl getName()geçersiz kılındığını ve değişkenin namegizlendiğini gösterir:

public class Main {

    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.name); // prints Parent (since hiding)
        System.out.println(p.getName()); // prints Child (since overriding)
    }
}

class Parent {
    String name = "Parent";

    String getName() {
        return name;
    }
}

class Child extends Parent {
    String name = "Child";

    String getName() {
        return name;
    }
}

0

Çalışma zamanında, geçersiz kılınan bir yöntemin alt sürümü, yöntem çağrısının bir üst veya alt sınıf yönteminde tanımlanmış olup olmadığına bakılmaksızın her zaman bir örnek için yürütülür. Bu şekilde, ParentClassName.method () sözdizimi kullanılarak ana yönteme yapılan açık bir çağrıya başvurulmadıkça ana yöntem asla kullanılmaz. Alternatif olarak, yönteme yapılan çağrı üst sınıfta tanımlanmışsa, çalışma zamanında gizli bir yöntemin üst sürümü her zaman yürütülür.


0

Yöntemin geçersiz kılınmasında , yöntem çözümlemesi, çalışma zamanı nesnesi temelinde JVM tarafından yapılır. Yöntem gizlemede ise, yöntem çözümlemesi derleyici tarafından referans temelinde yapılır. Böylece,

Kod şu şekilde yazılsaydı:

public static void main(String[] args) {
        Animal myCat = new Cat();        
        myCat.testClassMethod();        
    }

Çıktı aşağıdaki gibi olacaktır:
Animal sınıf metodu.


0

Alt sınıf aynı statik yönteme sahip olduğunda derleyici süper sınıf yöntem uygulamasını gizlediği için hiding olarak adlandırılır.

Derleyicinin geçersiz kılınan yöntemler için kısıtlı bir görünürlüğü yoktur ve hangisinin kullanılacağına yalnızca çalışma zamanı sırasında karar verilir.


0

Bu, geçersiz kılma ve gizleme arasındaki farktır:

Hayvan a = yeni Kedi ();

a.testClassMethod (), yöntem gizlemenin bir örneği olduğu için üst sınıfta yöntemi çağıracaktır. Çağrılacak yöntem, referans değişkeninin türüne göre belirlenir ve derleme zamanında karar verilir.

a.testInstanceMethod (), yöntemi geçersiz kılma örneği olduğu için alt sınıfta yöntemi çağıracaktır. Çağrılacak yöntem, çalışma zamanında yöntemi çağırmak için kullanılan nesne tarafından belirlenir.


0

Bunun henüz tam olarak açıklanmadığını düşünüyorum. Lütfen aşağıdaki örneğe bakın.

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal");
    }
}


public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat");
    }

    public static void main(String[] args) {
        Animal myCat = new Cat();
        Cat myCat2 = new Cat();
        myCat.testClassMethod();
        myCat2.testClassMethod();
        
        
        myCat.testInstanceMethod();
        myCat2.testInstanceMethod();
    }
}

Çıktı aşağıdaki gibi olacaktır.

The static method in Animal
The static method in Cat
The instance method in Cat
The instance method in Cat

-1

Java'da statik yöntem gizleme nasıl oluyor? Cat sınıfı, Hayvan sınıfını genişletiyor. Yani Cat sınıfında her iki statik yöntem de olacaktır (yani, Child sınıfının statik yöntemi ve Parent sınıfının statik yöntemi). Ancak JVM, Parent statik yöntemini nasıl gizler? Yığın ve Yığın'da nasıl işler?


Bu bir cevap değil. Sorulan sorunun bir uzantısıdır. Ayrı bir sorunun kendisi veya sorunun yorumlarının bir parçası olabilir.
Sri9911
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.