javaabstractmodifiers

Can an overriding method have a different access specifier from that in the base class?


Which access modifier, in an abstract class, do I have to use for a method, so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?

public abstract class A {

    ??? void method();
}

public class B extends A {
    @Override
    public void method(){
        // TODO
    }
}

public class C extends B {
    @Override
    private void method(){
        // TODO
    }
}

I know that there will be a problem with static binding, if someone calls:

// Will work
A foo = new B()
foo.method();

// Compiler ?
A foo = new C();
foo.method();

But maybe there is another way. How I can achieve that?


Solution

  • It is possible to relax the restriction, but not to make it more restrictive:

    public abstract class A {
        protected void method();
    }
    
    public class B extends A {
        @Override
        public void method(){    // OK
        }
    }
    
    public class C extends A {
        @Override
        private void method(){    // not allowed
        }
    }
    

    Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.

    I would recommend using interfaces to selectively expose or hide the method:

    public interface WithMethod {
        // other methods
        void method();
    }
    
    public interface WithoutMethod {
        // other methods
        // no 'method()'
    }
    
    public abstract class A {
        protected void method();
    }
    
    public class B extends A implements WithMethod {
        @Override
        public void method(){
          //TODO
        }
    }
    
    public class C extends B implements WithoutMethod {
        // no 'method()'
    }
    

    ... then only work with the instances through the interfaces.