0

Java 7

I have the following interface:

public interface SqlOperator{

    public String apply(Object o);

    /**
    * @return an operator representing the set defined 
    * by inversing the image of {@this operator}.
    */
    public SqlOperator not();

    //Some other methods
}

And I have a few its implementations that look like:

public class Foo implements SqlOperator{

    public SqlOperator not(){
        return new Foo(){
            @Override
            public String apply(Object o){
                return String.format("NOT (%s)", super.apply(o));
            }
        };
    }

    //other methods implementation
}

and this

public class Bar implements SqlOperator{

    public SqlOperator not(){
        return new Bar(){
            @Override
            public String apply(Object o){
                return String.format("NOT (%s)", super.apply(o));
            }
        };
    }

    //other methods implementation
}

The thing is the not() method is pretty much the same for all implementation for now (Currently I have 7 ones) except the class to be instantiated with the new operator. Is there a way to avoid wiritng such boilerplate code any time I need to implement the SqlOperator.

3
  • what java version are you using? Commented Oct 8, 2015 at 8:51
  • Can I suggest that not(foo) would be a better API than foo.not() - it would be better to use composition to build up your expression. It also makes implementing and or or operators easier: and(foo, bar) rather than foo.and(bar) etc. This means that your SqlOperator interface would contain simply the apply method. Commented Oct 8, 2015 at 8:53
  • @AndyTurner Well, I thought about it. But the not method is operator-specific. Commented Oct 8, 2015 at 8:55

4 Answers 4

3

In pre-Java-8 times the standard option was to create an abstract class like AbstractSqlOperator implements SqlOperator which defines methods having some standard implementation. Then concrete implementations extend this abstract class rather than implement the interface directly.

Java-8 introduced a new way to do this using default methods:

public interface SqlOperator{

    public String apply(Object o);

    /**
    * @return an operator representing the set defined 
    * by inversing the image of {@this operator}.
    */
    default public SqlOperator not() {
        return new SqlOperator(){
            @Override
            public String apply(Object o){
                return String.format("NOT (%s)", SqlOperator.this.apply(o));
            }

            @Override
            public SqlOperator not() {
                // double not: just return the original operator
                return SqlOperator.this;
            }
        };
    }

    //Some other methods
}
Sign up to request clarification or add additional context in comments.

4 Comments

Well, the interface doesn't know about SomeImplementation.
@St.Antario, it can implement itself. See the updated answer
Want you have the Stack Exception ? as you cal apply from apply ?
@DamianLeszczyński-Vash, I call apply for the different object (outer instance). Try, it works.
2

Wrap your SqlOperator interface in an abstract class. Then let your SomeImplementation classes inherit from the abstract class. The abstract class will implement the interface not() method.

public abstract class AbstractImplementation implements SqlOperator
{
    public SqlOperator not(){
    return new SomeImplementation(){
        @Override
        public String apply(Object o){
            return String.format("NOT (%s)", super.apply(o));
        }
    };
}

//...
public class SomeImplementation extends AbstractImplementation
{
    //... your stuff here
}

Comments

2

You have plenty of options.

If you're on Java8, you can create a default method within the SqlOperator interface and there will be no need to implement it across the subclasses:

public interface SqlOperator{
    public default SqlOperator not() {
        return new SomeImplementation(){
            @Override
            public String apply(Object o){
                return String.format("NOT (%s)", super.apply(o));
            }
        };
    }
}

However, if you still haven't upgraded to Java8, then you could just introduce an abstract subclass of SqlOperator where you will have the not() implementation and then all the other implementors could extend this abstract class. For example:

public abstract class AbstractSqlOperator implements SqlOperator {
    public SqlOperator not() {
        return new SomeImplementation(){
            @Override
            public String apply(Object o){
                return String.format("NOT (%s)", super.apply(o));
            }
        };
    }
}

public class SomeImplementation extends AbstractSqlOperator { ... }

2 Comments

Couldn't you look at the updated question? I believe I wasn't clear about what I actually wanted...
Yup. Then the approach with the abstract class, which contains the shared not() implementation will suite for your case.
1

IMHO you have some design issue, as you clone the code. Already presented solution base on inheritance i would rather go in composition.

The goal is to crate a SqlOperator that negate other operator.

I would remove the not() from SqlOperator interface. Each operator should be separated. NOT,LIKE, AND, OR are the operators used in SQL that operate on expression. Naturally an operator AND should do not know how to negate it.

public interface SqlOperator{
    public String apply(Object o);
}

class NotOperator implements SqlOperator {

    private final SqlOperator operator;

    NotOperator(SqlOperator operator) {
       this.operator = operator;
    }

    public String apply(Object o) {
        return String.format("NOT (%s)", operator.apply(o));
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.