I need super.super.method () & # 8594; Possible design flaw?

I found that I need to call super.super.method () in java, which is not possible.

I'm just wondering if I have a design flaw in my design or not?

Classes:

package solvers.command; /** * * @author student */ public abstract class Command { private boolean executed; //executed state /** * Constructs a new Command object. * * @modifies this.executed = false */ public Command() { this.executed = false; } /** * Executes this command. * * @modifies executed = true * @pre {@code !executed} * @throws IllegalStateException if {@code executed} */ public void execute() { if (executed) { throw new IllegalStateException("solvers.command.Command.execute: already executed"); } executed = true; } /** * Undoes this command. * * @modifies executed = false * @pre {@code executed} * @throws IllegalStateException if {@code !executed} */ public void undo() { if (!executed) { throw new IllegalStateException("solvers.command.Command.undo: not executed yet"); } executed = false; } /** * Returns the executed state * * @return executed state */ public boolean getExecuted() { return executed; } } package solvers.command; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * * @author student */ public class CompoundCommand extends Command { List<Command> commands; //list of commands /** * Creates a new CompoundCommand. * * @modifies this.commands is initialised */ public CompoundCommand() { super(); this.commands = new ArrayList<>(); } /** * Adds a command to the list of commands. * * @param command The new command * @pre {@code command != null} * @throws IllegalArgumentException if {@code command == null} */ public void add(final Command command) { if (command == null) { throw new IllegalArgumentException("solvers.command.CompoundCommand.add: " + "command == null"); } commands.add(command); } /** * Removes a command from the list of commands. * * @param command The command to be removed * @pre {@code command != null && commands.contains(command} * @throws IllegalArgumentException if {@code command == null || !commands.contains(command)} */ public void remove(final Command command) { if (command == null) { throw new IllegalArgumentException("solvers.command.CompoundCommand.remove: " + "command == null"); } if (!commands.contains(command)) { throw new IllegalArgumentException("solvers.command.CompoundCommand.remove:" + "command is not found in commands"); } commands.remove(command); } /** * Returns if the list of commands is empty. * * @return {@code commands.isEmpty()} */ public boolean isEmpty() { return commands.isEmpty(); } @Override public void execute() { super.execute(); for (Command c : commands) { c.execute(); } } @Override public void undo() { super.undo(); Collections.reverse(commands); for (Command c : commands) { c.undo(); } Collections.reverse(commands); } } package solvers.command; /** * * @author student */ public class ExecutedCompoundCommand extends CompoundCommand { /** * Creates a new ExecutedCompoundCommand. */ public ExecutedCompoundCommand() { super(); } @Override public void add(final Command command) { if (!command.getExecuted()) { throw new IllegalStateException("solvers.command.ExecutedCompoundCommand.add: " + "command has not been executed yet."); } super.add(command); } @Override public void execute() { super.super.execute(); /* Does not work obviously */ for (Command c : commands) { if (!c.getExecuted()) { c.execute(); } } } } 

Basically, I need the security of the execute() command, while I don't need the CompoundCommand execute () implementation for the ExecutedCompoundCommand , but I just want to rely on the add (), remove ()) and undo () of the CompoundCommand operation.

As a student, working on a project with the required javadoc and unit testing, it is really necessary that there is as little code duplication as it can only do more work.

+4
source share
4 answers

I think this is a design mistake. You can apply the template method template [GOF 325]

Purpose: determination of the skeleton of the algorithm in the operation, derivation of some steps to subclasses. The template method allows you to redefine subclasses of certain stages of the algorithm without changing the algorithm structure.

From a set of four design patterns

You want to be sure that certain steps are being taken. Thus, you must make the final template execute () method and delegate the doExecute () method, which can add additional logic and must be implemented by subclasses.

 public final void execute() { importantOperation(); runsAlways(); doExecute(); } public abstract void doExecute(); // Override in subclasses 
+2
source

There are several ways to fix this, and the best way depends on your intentions. Here are some suggestions:

Create a new CommandList class that supports add (), remove (), and undo ().

CompoundCommand extends Command and has a list of commands.

ExecutedCompoundCommand extends Command and has a list of commands.

Another option is to create a new Command subclass that supports common operations and inherits the Command execute () method.

CompoundCommand extends it and cancels only execution.

ExecutedCompoundCommand will also expand it, and therefore its super.execute () will execute the execute () command.

+1
source

Use a delegate template for general functionality instead of inheritance. Or a template template if you want to use inheritance.

+1
source

Take a look here . This basically explains why you never need to do what you want to do.

As indicated in the link:

You cannot bypass the behavior of the parent class. Sometimes it makes sense to bypass your class behavior (in particular, from one method), but not with parents.

In the example shown in the link, the argument is that the "middle" class, so to speak, performs some functionality checks or reality checks that will bypass the "skip" class in the hierarchy.

Read this short article about the benefits of encapsulation.

0
source

All Articles