0

I have a Java class called Program whose rough skeleton is like this:

public class Program {

    public Program(AST ast){
        ...
        new RewriteRule1().rewriteAll();
        new RewriteRule2().rewriteAll();
    }


    interface RewriteRule {
        // find a line where this rewrite rule can be applied
        public abstract Optional<Integer> findRewrite();
    
        // apply this rewrite rule to the program at given line
        // destructively modifies the program!
        public abstract void doRewrite(int line);
    
        // repeatedly find and rewrite all instances
        public default void rewriteAll(){
            while (true){
                Optional<Integer> line = findRewrite();
                if (!line.isPresent())
                    break;
                doRewrite(line.get());
            }
        }
        
    }

    class RewriteRule1 implements RewriteRule{

        @Override
        public Optional<Integer> findRewrite() {}

        @Override
        public void doRewrite(int l1) {}
        
    }

    class RewriteRule2 implements RewriteRule{

        @Override
        public Optional<Integer> findRewrite() {}

        @Override
        public void doRewrite(int l1) {}
    }

}

Here, I want to have a notion called RewriteRule that has two distinct abstract methods called findRewrite and doRewrite. I want these to be abstract but I want to have a method called rewriteAll which is common to all subtypes of RewriteRule.

In the actual program, I create an instance of every rewrite rule and I call rewriteAll() individually. This feels wrong. I want to be able to just refer to the subtype RewriteRule1 instead of having to create an instance. Creating an instance feels suboptimal since there is no data associated with it.

But the issue is that

  • If RewriteRule is an interface, I can't force it to have static abstract methods. Java is asking me to give an implementation for all static methods.
  • If RewriteRule is an abstract class, I can't force it to have static unimplemented methods either.

What is the best way to organize this code?

1 Answers1

1

Sounds like you can use an enum instead of the interface:

enum Rewrite {
    RULE_1 {
        @Override
        public Optional<Integer> findRewrite() {}
    
        @Override
        public void doRewrite(int l1) {}            
    },
    RULE_2 {
        ...
    };

    public abstract Optional<Integer> findRewrite();

    public abstract void doRewrite(int line);

    public void rewriteAll() {
        Optional<Integer> line;
        while ((line = findRewrite()).isPresent())
            doRewrite(line.get());
    }
}

public Program(AST ast) {
    ...
    for (Rewrite rule : Rewrite.values())
        rule.rewriteAll();
}

If you still want the interface, you can have the enum implement it instead of declaring its own abstract methods.

shmosel
  • 49,289
  • 6
  • 73
  • 138