简体   繁体   中英

Ensure method A is called after every call of B (an abstract implemented method)?

Having this tasteful class

     public abstract class CakeSkill 
     {

         //.. 

         boolean cherry=false;

         private void finalMandatoryTouch()
         {        
              cherry=true;
         }                
         abstract public void cook();
     }

A class that extends it would be something like

     class Cheff extends CakeSkill 
     {
         //..

         void cook()
         {
         //..Secret recipe
         }     
     }

But of course this won't work,

finalMandaroryTouch() hasn't been called, then no cake will end with a cherry..

[EDIT]

This one could be a solution

       class MemoriousCheff extends CakeSkill 
       {
           //..

           void cook()
           {
               //..Secret recipe
               finalMandatoryTouch();
           }     
       }

but requires:

  • Cheff to have a perfect memory that don't forget to call finalMandatoryTouch()
  • Making finalMandatoryTouch() to be protected (at least)

[/EDIT]

It would be great! (but no Java) if something like this could be done

  abstract public void cook()   
  {  
    @implementedMethod

    finalMandatoryTouch();        
  }

How can be implemented this useful functionality?

Thank you very much

Change cook to a protected method cookImpl then have a public final method called cook:

public final void cook()
{
    cookImpl();
    finalMandatoryTouch();
}

protected abstract void cookImpl();

That way the subclass only needs to worry about cookImpl , but callers of cook get the cherry on top. Callers not in the same package or class hierarchy won't even see cookImpl , so won't be able to call it directly.

This is the template method pattern , basically.

It's called the Template method pattern.

final public void cook() {  
    mainCookRecipe();
    finalMandatoryTouch();        
}

abstract public void mainCookRecipe();
public abstract class CakeSkill {

    public void cook() {
        doCook();
        finalMandatoryTouch();
    }

    protected abstract doCook();

    private finalMandatoryTouch() { ... }
}

Etc.

You could change your cook() method to an actual method and then invoke a separate abstract method as well as your finalMandatoryTouch() method.

In your abstract class:

 public void cook() {
     specificCook();
     finalMandatoryTouch();
 }

 abstract void specificCook();

It seems that inheritance is not the right way to model your problem. In Java you can only inherit from one class, and since it's also a very static relationship, it limits your chef in the skills he can perform.

A better way would be to use composition. Cooking skills could be strategies that the chef performs:

interface CookingSkill {
  void cook();
}

class CakeSkill implements CookingSkill {
  private boolean cherry = false;
  private void finalMandatoryTouch() {
    cherry = true;
  }
  public void cook() {
    //...
    finalMandatoryTouch();
  }
}

class Chef {
  private CookingSkill cookingSkill;
  // getters and setters ...
  public void cook() {
    // ...
    cookingSkill.cook();
    // ...
  }
}

Now you can assign different cooking skills to your chef.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM