Question

Est-il possible de forcer les classes d'enfants pour remplacer une méthode non abstraite de super classe?

Je dois être en mesure de créer des instances de la classe mère, mais si une classe étend cette classe, il doit donner sa propre définition de certaines méthodes.

Était-ce utile?

La solution

Il n'y a aucun moyen appliqué compilateur direct pour ce faire, pour autant que je sache.

Vous pouvez travailler autour d'elle par pas faire la instanciable de classe parent, mais au lieu de fournir une méthode de fabrication qui crée une instance de certains (possible privé) sous-classe qui a la mise en œuvre par défaut:

public abstract class Base {
  public static Base create() {
    return new DefaultBase();
  }

  public abstract void frobnicate();

  static class DefaultBase extends Base {
    public void frobnicate() {
      // default frobnication implementation
    }
  }
}

ne peut pas new Base() d'écriture maintenant, mais vous pouvez le faire Base.create() pour obtenir la mise en œuvre par défaut.

Autres conseils

Comme d'autres ont des branches, vous ne pouvez pas le faire directement.

Mais une façon de le faire est d'utiliser le modèle de stratégie , comme ceci:

public class Base {
    private final Strategy impl;

    // Public factory method uses DefaultStrategy
    // You could also use a public constructor here, but then subclasses would
    // be able to use that public constructor instead of the protected one
    public static Base newInstance() {
        return new Base(new DefaultStrategy());
    }

    // Subclasses must provide a Strategy implementation
    protected Base(Strategy impl) {
        this.impl = impl;
    }

    // Method is final: subclasses can "override" by providing a different
    // implementation of the Strategy interface
    public final void foo() {
        impl.foo();
    }

    // A subclass must provide an object that implements this interface
    public interface Strategy {
        void foo();
    }

    // This implementation is private, so subclasses cannot access it
    // It could also be made protected if you prefer
    private static DefaultStrategy implements Strategy {
        @Override
        public void foo() {
            // Default foo() implementation goes here
        }
    }
}

Pensez à faire une interface avec cette méthode. descendants de classe devront la mettre en œuvre.

Je pense que la meilleure façon est de créer une classe abstraite qui hérite de la classe de base:


public class Base {
    public void foo() {
        // original method
    }
}

abstract class BaseToInheritFrom extends Base {
    @Override
    public abstract void foo();
}

class RealBaseImpl extends BaseToInheritFrom {
    @Override
    public void foo() {
        // real impl
    }
}

Non, c'est le point de l'ensemble d'une méthode abstraite. Quelle est votre cas d'utilisation? Peut-être que nous pouvons penser en fonction du besoin sous-jacent.

Que diriez-vous ceci: dans l'implémentation par défaut de la méthode, la réflexion d'utiliser pour obtenir la classe exacte de l'objet. Si la classe ne correspond pas à votre classe de base exactement, jeter un RuntimeException ou équivalent.

public class Parent {

    public void defaultImpl(){
        if(this.getClass() != Parent.class){
            throw new RuntimeException();
        }
    }

}

Il y a une raison il est impossible!

La classe dérivée pourrait simplement appel la mise en œuvre de la classe de base lors de la substitution de la méthode.

Alors, quel est le point de forcer la classe à remplacer votre méthode? Je ne pense pas qu'il y ait un avantage.

Réponse serait pas. Vous pouvez redessiner à l'aide modèle de conception de modèle. Il peut vous aider.

Vous pouvez faire vos classes d'enfants à mettre en œuvre une interface. L'interface peut ou ne peut pas être mis en œuvre par la classe super.

Vous pouvez toujours faire la classe de base ont une méthode qui jette une exception.

Techniquement, la classe de base a défini la méthode, mais il n'est pas utilisable sans redéfinissant la méthode. Dans ce cas, je préfère une exception d'exécution car ils ne nécessitent pas explicite lancers francs déclaration. Voici un exemple

public class Parent {

  public void doStuff() {
    throw new RuntimeException("doStuff() must be overridden");
  }

}

public class Child extends Parent {

  @Override
  public void doStuff() {
    ... all is well here ...
  }

}

L'inconvénient est que cela ne l'empêche pas la création d'objets Base; Cependant, toute personne qui tenterait d'utiliser l'un des « doit être remplacée » méthodes vont bientôt trouver qu'ils devraient avoir la classe surchargée.

Bien que cette solution répond à la description de la demande bien, votre demande serait probablement bénéficier de ne pas exiger une solution comme celle-ci. Il est beaucoup mieux d'accidents d'exécution d'éviter avec les contrôles du compilateur, qui est ce que le mot-clé abrégé fournit.

Je refléteront les autres réponses et dire qu'il n'y a aucun moyen appliqué compilateur pour forcer les classes dérivées pour remplacer une méthode non abstraite. Le point entier de faire une méthode abstraite est de définir qui doit exister une méthode avec cette signature, mais ne peut pas être spécifié au niveau de base et par conséquent doit être spécifiée à un niveau dérivé. S'il y a un travail, la mise en œuvre non trivial (comme ce n'est pas vide et ne jetez pas une exception ou afficher un message) d'une méthode au niveau de base, alors ce n'est pas strictement nécessaire pour un appel à la méthode d'un consommateur de la classe dérivée pour réussir. Ainsi, le compilateur ne doit pas appliquer une méthode qui remplaçant peut fonctionner tout à fait avec succès sur la base ou les niveaux dérivés.

Dans les situations où vous voulez une classe dérivée de passer outre l'implémentation de travail, il devrait être assez évident que la mise en œuvre de base ne fait pas ce que veulent les consommateurs de la classe dérivée; la classe de base ne soit pas assez mise en œuvre, ou le mauvais. Dans ces cas, vous devez faire confiance qu'un programmeur provenant de votre classe saura ce qu'il fait et de savoir ainsi que les besoins de la méthode à être outrepassées, car elle ne produit pas la bonne réponse dans le cadre de l'utilisation de son nouvel objet.

Je peux penser à une chose que vous pourriez faire. Il faudrait une base abstraite, avec un scellé (final pour les Javaheads) la mise en œuvre « par défaut ». De cette façon, il y a une mise en œuvre de base de la méthode qui est facilement disponible pour l'utiliser comme si elle était une classe « de base », mais afin de définir une autre classe pour un nouveau scénario, vous devez revenir à la classe abstraite, et sont ainsi contraints de ré-écrire la méthode. Cette méthode pourrait être la seule chose abstraite de la classe, donc en vous permettant de faire usage des mises en œuvre de base d'autres méthodes:

public abstract class BaseClass
{
   public abstract void MethodYouMustAlwaysOverride();

   public virtual void MethodWithBasicImplementation() { ... }
}

public final class DefaultClass:BaseClass
{
   public override void MethodYouMustAlwaysOverride() { ... }

   //the base implementation of MethodWithBasicImplementation 
   //doesn't have to be overridden
}

...

public class DerivedClass:BaseClass
{
   //Because DefaultClass is final, we must go back to BaseClass,
   //which means we must reimplement the abstract method
   public override void MethodYouMustAlwaysOverride() { ... }

   //again, we can still use MethodWithBasicImplementation, 
   //or we can extend/override it
   public override void MethodWithBasicImplementation() { ... }
}

Cependant, cela a deux inconvénients. Tout d'abord, parce que vous n'avez pas accès à la mise en œuvre de defaultclass par héritage, vous ne pouvez pas étendre la mise en œuvre de defaultclass, ce qui signifie que pour faire ce que defaultclass fait, plus un peu plus, vous devez réécrire le code de defaultclass, violant DRY. En second lieu, cela ne fonctionne que pour un niveau d'héritage, parce que vous ne pouvez pas forcer si vous permettez primordial héritage de ClasseDérivée.

peut-être cette aide:

class SuperClass {

    void doStuff(){

        if(!this.getClass().equals(SuperClass.class)){

            throw new RuntimeException("Child class must implement doStuff Method");
        }else{
            //ok
            //default implementation
        }
    }
}

class Child extends SuperClass{

    @Override
    void doStuff() {
        //ok
    }
}

class Child2 extends SuperClass{

}


 new SuperClass().doStuff(); //ok
 new Child().doStuff();         //ok
 new Child2().doStuff();        //error

ok, nous allons apprendre de cette façon. Je respecte les lignes directrices de style java et utilisez la syntaxe java. Ainsi, on suppose que l'héritage multiple et les modèles C de ne sont pas disponibles.

faire la méthode de classe parent abstraite n'est pas un must, en POO vous utilisez le concept de polymorphisme. vous pouvez utiliser la même méthode en deux ou plusieurs façons différentes. Ceci est appelé méthode remplaçant.

Prenons un exemple.

    public class Animal{
       public void makeSound(){
          System.out.println("Animal doesn't know how to make sound");
       }

    }

    public class PussyCat extends Animal{
        public void makeSound(){

           System.out.println("meowwww !!!");
        }

        public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
    }

imprimera "meowww !!!" sur l'écran.

mais cela ne signifie pas que la méthode makeSound doit être redéfinie dans la classe enfant.

Si vous avez besoin de la classe de l'enfant d'être obligé de remplacer les méthodes, vous mieux mettre en œuvre une interface par la classe.

      public Interface audible{
         public void makeSound();

      }

      public class pussyCat implements audible{
          // now you must implement the body of makeSound method here
          public void makeSound(){
            System.out.println("meowwww !!!"); 
          }

          public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
      }

imprimera aussi « Miaaaou !!! » sur l'écran

Il ne peut pas être recommandé, mais vous pouvez jeter un exeption (quelque chose comme MethodeMustBeOverRiddenExp) dans votre mise en œuvre de Methode. Bien sûr, il est RunTime mais force peut être mieux que nuthing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top