É possível, mas não do jeito que você o tem.
Você tem que adicionar um construtor no-args à classe base e é isso!
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";
}
}
Quando você não adiciona um construtor (qualquer) a uma classe, o compilador adiciona o construtor sem arg padrão para você.
Quando o padrão nenhum arg chama super (); e como você não o tem na superclasse, você recebe aquela mensagem de erro.
Isso é sobre a própria questão.
Agora, expandindo a resposta:
Você está ciente de que criar uma subclasse (comportamento) para especificar um valor diferente (dados) não faz sentido ?? !!! Espero que você faça.
Se a única coisa que muda é o "nome", então uma única classe parametrizada é o suficiente!
Então você não precisa disso:
MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");
ou
MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();
Quando você pode escrever isto:
MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");
Se eu fosse alterar a assinatura do método do construtor BaseClass, teria que alterar todas as subclasses.
Bem, é por isso que a herança é o artefato que cria o acoplamento HIGH, o que é indesejável em sistemas OO. Deve ser evitado e talvez substituído por composição.
Pense se você realmente precisa deles como subclasse. É por isso que você vê muitas vezes interfaces usadas em vez de:
public interface NameAware {
public String getName();
}
class A implements NameAware ...
class B implements NameAware ...
class C ... etc.
Aqui B e C poderiam ter herdado de A, o que teria criado um acoplamento muito ALTO entre eles, ao usar interfaces o acoplamento é reduzido, se A decidir que não será mais "NameAware" as outras classes não quebrarão.
Claro, se você quiser reutilizar o comportamento, isso não funcionará.