Java hatası: Örtük süper yapıcı, varsayılan kurucu için tanımsız


89

Yapısında buna benzeyen bazı basit bir Java kodum var:

abstract public class BaseClass {
    String someString;
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public ASubClass(String someString) {
        super(someString);
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

BaseClassHer biri getName()yöntemi kendi yolunda uygulayan epeyce alt sınıfa sahip olacağım ( şablon yöntem kalıbı ).

Bu iyi çalışıyor, ancak alt sınıflarda yedek kurucunun olmasını sevmiyorum. Yazması daha fazladır ve sürdürmesi zordur. Yapıcının yöntem imzasını BaseClassdeğiştirirsem, tüm alt sınıfları değiştirmem gerekirdi.

Yapıcıyı alt sınıflardan kaldırdığımda, bu derleme zamanı hatasını alıyorum:

Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor

Yapmaya çalıştığım şey mümkün mü?


1
Lütfen 'fazlalık' kurucuyu bırakın! Kodunuzun okunabilirliğini korur ve tüm modern IDE'ler onu otomatik olarak oluşturabilir, böylece bir kısayol tuşlamanız yeterlidir.
Andreas Dolk

3
Bir yıl sonra kendi sorumu yeniden okudum ve mat b'nin önerdiği gibi yapıcıları (temel sınıftaki dahil) kaldırıp örnekleri oluşturmak için statik bir fabrika yöntemi kullanabileceğimi anladım.
Joel

Yanıtlar:


146

Bu hatayı, yapıcısı olmayan bir sınıfın , argümansız ve aşağıdaki koda eşdeğer olan varsayılan bir kurucuya sahip olması nedeniyle alırsınız :

public ACSubClass() {
    super();
}

Bununla birlikte, BaseClass'ınız bir kurucu bildirdiği için (ve bu nedenle, derleyicinin aksi takdirde sağlayacağı varsayılan, argümansız kurucuya sahip olmadığı için) bu yasa dışıdır - BaseClass'ı genişleten bir sınıf, super();bağımsız değişken olmayan bir kurucu olmadığından çağrı yapamaz. BaseClass'ta.

Bu muhtemelen biraz sezgiseldir, çünkü bir alt sınıfın otomatik olarak temel sınıfın sahip olduğu herhangi bir kurucuya sahip olduğunu düşünebilirsiniz.

Bunu aşmanın en basit yolu, temel sınıfın bir yapıcı bildirmemesi (ve bu nedenle varsayılan, arginsiz yapıcıya sahip olması) veya bildirilmiş bir argonsuz kurucuya (kendi başına veya diğer oluşturucuların yanında) sahip olmasıdır. Ancak çoğu zaman bu yaklaşım uygulanamaz - çünkü sınıfın yasal bir örneğini oluşturmak için yapıcıya iletilen her türlü argümana ihtiyacınız vardır.


17
"Bu muhtemelen biraz sezgiseldir çünkü bir alt sınıfın otomatik olarak temel sınıfın sahip olduğu herhangi bir kurucuya sahip olduğunu düşünebilirsiniz." +1
Mr_and_Mrs_D

2
Gelecek nesillerin iyiliği için, gelecekteki okuyucular için çözümümü önereceğim: tartışmasız bir kurucu yaratın BaseClassama basitçe bir UnsupportedOperationExceptionveya başka bir şey atmasını sağlayın . Bu en iyi çözüm değil (yanlış bir şekilde sınıfın tartışmasız bir kurucuyu destekleyebileceğini gösteriyor), ama düşünebildiğim en iyisi.
JMTyler

51

Bu hata için Google'ı arayanlar ve buraya gelenler için: Bunu almanın başka bir nedeni olabilir. Eclipse, proje kurulumunuz olduğunda bu hatayı verir - sistem konfigürasyonu uyumsuzluğu.

Örneğin, Java 1.7 projesini Eclipse'e aktarırsanız ve 1.7'yi doğru bir şekilde kurmadıysanız, bu hatayı alırsınız. Sonra ya gidebilirsiniz Project - Preference - Java - Compilerve switch to 1.6 or earlier; veya Window - Preferences - Java - Installed JREsJRE 1.7 kurulumunuza gidin ve ekleyin / düzeltin.


2
Eclipse'de görünürde bir sebep olmadan bu hatayı aldım. Sonra çalışma alanını temizledim (menü Proje -> Temizle ...) ve gitti.
erickrf

7

Mümkün ama sahip olduğunuz yol değil.

Temel sınıfa argümansız bir kurucu eklemelisiniz ve işte bu kadar!

public abstract class A {
    private String name;
    public A(){
        this.name = getName();
    }
    public abstract String getName();


    public String toString(){
        return "simple class name: " + this.getClass().getSimpleName() + " name:\"" + this.name + "\"";
    }
}
class B extends A {
    public String getName(){
        return "my name is B";
    }
    public static void main( String [] args ) {
        System.out.println( new C() );
    }
}
class C extends A {
    public String getName() {
        return "Zee";
    }
}

Bir sınıfa bir yapıcı (herhangi) eklemediğinizde, derleyici sizin için varsayılan no arg oluşturucusunu ekler.

Varsayılan hiçbir argüman super () 'i çağırdığında; ve süper sınıfta olmadığından bu hata mesajını alıyorsun.

Kendisinin sorusu bu.

Şimdi cevabı genişleterek:

Farklı bir değeri (verileri) belirtmek için bir alt sınıf (davranış) oluşturmanın bir anlamı olmadığının farkında mısınız ?? !!! Umarım yaparsın.

Değişen tek şey "isim" ise, parametreleştirilmiş tek bir sınıf yeterlidir!

Yani buna ihtiyacınız yok:

MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");

veya

MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();

Bunu ne zaman yazabilirsin:

MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");

BaseClass yapıcısının yöntem imzasını değiştirirsem, tüm alt sınıfları değiştirmem gerekirdi.

İşte bu yüzden kalıtım, OO sistemlerinde istenmeyen YÜKSEK kuplajı yaratan eserdir. Önlenmeli ve belki kompozisyonla değiştirilmelidir.

Onlara gerçekten alt sınıf olarak ihtiyacınız olup olmadığını düşünün. Bu nedenle, sıklıkla kullanılan arayüzleri görüyorsunuz:

 public interface NameAware {
     public String getName();
 }



 class A implements NameAware ...
 class B implements NameAware ...
 class C ... etc. 

Burada B ve C, aralarında çok YÜKSEK bir bağlantı oluşturacak olan A'dan miras almış olabilir, arayüzler kullanılarak bağlantı azaltılır, A artık "NameAware" olmayacağına karar verirse diğer sınıflar bozulmaz.

Elbette, davranışı yeniden kullanmak istiyorsanız bu işe yaramayacaktır.


2
Evet, ancak örneklerinizin doğru bir şekilde başlatıldığından artık emin olamazsınız (örneğin, bu özel durumda adlara sahip olursunuz)
ChssPly76

@ ChssPly76: Evet, ancak bunun nedeni muhtemelen kalıtımın kötü bir şekilde kullanılmasıdır. Cevabımı kapsayacak şekilde genişlettim.
OscarRyz

4

JRE ayarlanmadığında da bu hatayı alabilirsiniz. Öyleyse, projenize JRE Sistem Kitaplığı eklemeyi deneyin .

Eclipse IDE altında:

  1. Proje -> Özellikler menüsünü açın veya Paket Gezgini'nde projenize sağ tıklayın ve Özellikler'i seçin (Windows'ta Alt + Enter, Mac'te Command + I)
  2. tıklayın Java Build Path sonra Kütüphaneler sekmesi
  3. Modulepath veya Classpath seçin ve Add Library ... butonuna basın
  4. JRE Sistem Kitaplığı'nı seçin ve İleri'ye tıklayın
  5. tutmak Çalışma Alanı öntanımlı JRE seçilen (ayrıca başka bir seçenek alabilir) ve tıklama Finish
  6. son olarak Uygula ve Kapat'a basın .

2

Başka bir yol, türetilmiş sınıf yapıcısında birinci ifade olarak gerekli bağımsız değişkenle super () 'i çağırmaktır.

public class Sup {
    public Sup(String s) { ...}
}

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}

0

Alt sınıf yapıcısında birinci ifade olarak süper sınıf yapıcısına çağrı yoksa Eclipse bu hatayı verecektir.


0

Necroposting için özür dilerim ama bugün bu problemle karşı karşıya kaldık. Bu problemle karşı karşıya kalan herkes için - olası nedenlerden biri - superyöntemin ilk satırında aramıyorsunuz . İkinci, üçüncü ve diğer satırlar bu hatayı ateşler. Süper çağrısı yönteminizde ilk çağrı olmalıdır. Bu durumda her şey yolunda.


0

Yukarıdaki sorunu aşağıdaki gibi çözdüm:

  1. Proje'ye tıklayın.
  2. özellikler> Java Derleme Yolu> Kitaplık> JRE Sistem Kitaplığı> Düzenle'ye tıklayın
  3. Varsayılan sistemi seçin JRE ve Bitir
  4. Uygula ve kapat.

-1

Bu hatayı, temel sınıfa argümansız bir kurucu ekleyerek çözebilirsiniz (aşağıda gösterildiği gibi).

Şerefe.

 abstract public class BaseClass {
        // ADD AN ARGUMENTLESS CONSTRUCTOR TO THE BASE CLASS
        public BaseClass(){
        }

        String someString;
        public BaseClass(String someString) {
            this.someString = someString;
        }
        abstract public String getName();
    }

public class ACSubClass extends BaseClass {
    public ASubClass(String someString) {
        super(someString);
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

Bu, geçersiz nesneler (kümesiz olanlar someString) oluşturmayı kolaylaştırır ve dolayısıyla yapıcı olma amacını tamamen ortadan kaldırır.
Robert

-1

Bu hatayı aldım ve yöntemin yanından atılan bir istisnayı dene / yakala bloğuna kaldırarak düzelttim.

Örneğin: KİMDEN:

public static HashMap<String, String> getMap() throws SQLException
{

}

ALICI:

public static Hashmap<String,String> getMap()
{
  try{

  }catch(SQLException)
  { 
  }
}

Bu cevabın eksik bir kurucu için derleyici hatalarıyla hiçbir ilgisi yoktur.
Robert
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.