1
//cls_a is defined by system framework, so we cannot change its definition
public class cls_a {
  public void method_a();
}

//I add a new cls_b implemenation and would like to 
//add a new method_a(int) function
//and prevent client side to access cls_a.method_a()
public class cls_b extends cls_a {
  public void method_a(int a) {
    //do something for a
    method_a();
  }
}

//client side
cls_b b = new cls_b();
b.method_a(2); //it's okay
b.method_a(); //should give something error when compiling code

I would like to design cls_b so that the Java compiler will give an error when client side calls b.method_a(). Anyone knows how to do it in Java?

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
Sam Lu
  • 3,448
  • 1
  • 27
  • 39

6 Answers6

3

What I do now is adding a @Deprecated annotation to method_a() (see below example), so client side will get a warning. Since the warning is easy to be ignored, are there any way to make compiler giving an error?

public class cls_b extends cls_a {
  //add @Deprecated 
  @Deprecated @Override public void method_a() {
    super.method_a();
  }
  public void method_a(int a) {
    //do something for a
    method_a();
  }
}

Sam Lu
  • 3,448
  • 1
  • 27
  • 39
2

You can't do that because you cannot reduce the visibility of an inherited method (e.g. if it is public, you cannot make it private).

Why can't you reduce the visibility of a method in a Java subclass? explains why that is.

Community
  • 1
  • 1
Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
2

Once you make it public, then its scope is available over the project. There is no way to make a public function hidden from a specific class

Update: I just read your question again. I think you want other developers when calling the method_a() from b will get the exception. If it is what you want, then you can try

package com.test;


public class ClassA {
    public static void main (String args[]) {
        ClassB b = new ClassB();
        b.print();
    }
}

class ClassC {
    public void print() {
        System.out.println("printA");
    }
}

class ClassB extends ClassC {

    public void print() {
        try {
            throw new Exception("This method is dead");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void print(int i) {
        System.out.println(i);
    }
}
Thai Tran
  • 9,815
  • 7
  • 43
  • 64
  • This solution is a kind of runtime checking. I prefer to get a static checking solution (find the error at compiling stage). – Sam Lu Jan 20 '13 at 05:47
1

You can do this way: Expose a wrapper class for clients.

 public class cls_a_Wrapper {
      private cls_a a;

      cls_a_Wrapper(){
          a = new cls_a();
      }  

      //methods
      public void method_a_wrapper(){
           a.method_a();
      }
  }

 public class cls_b extends cls_a_Wrapper {
      public void method_a_wrapper(int a) {

           //delegate to wrapper class method if its allowed
           method_a_wrapper();
     }
  }

So now your client should user class cls_a_Wrapper class instead of cls_a.

So now you can control if you want to call base class's public method. This is Adapter Design patter.

If you don't want to call a public method :

  • don't provide method in your wrapper class.
  • OR change visibility of method in your wrapper class

Remember : For client original class doesn't exist. Client should treat wrapper class as the base class.

rai.skumar
  • 10,309
  • 6
  • 39
  • 55
  • There are lots of functions defined in cls_a. It will be a burden to use wrapper class solution. – Sam Lu Jan 20 '13 at 05:25
  • You can directly delegate to cls_a class methods as done in method_a_wrapper(). So methods will be very lightweight unless you want to put any check. But this approach is better in terms of design. – rai.skumar Jan 20 '13 at 05:28
  • have improved it bit more..hope it makes sense :) – rai.skumar Jan 20 '13 at 05:37
1

You cannot reduce a method's visibility in a subclass.

JDK solves similar problems with UnsupportedOperationException, e.g.

java.util.Arrays.UnmodifiableCollection

    ...
            public boolean add(E e) {
                throw new UnsupportedOperationException();
            }
    ...

java.util.Collection API marks this kind of methods as optional operation

boolean add(E e) Ensures that this collection contains the specified element (optional operation).
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • This solution is also a kind of runtime checking. I don't like it as the error can only be caught by test cases. I prefer to have a static checking solution (find the error at compiling stage). – Sam Lu Jan 20 '13 at 06:03
  • Right, I think JDK developers would also prefer to remove add(E e) from UnmodifiableCollection but this is impossible in OOP. – Evgeniy Dorofeev Jan 20 '13 at 06:13
0

To prevent client from accessing public function of base class is not a good choice. Even you can give a runtime exception or deprecated method, clients also could call your method by cls_a type.

cls_a a = new cls_b();
//...
a.method_a();

The better way is to give a default implementation of method_a. For your code,

public class cls_b extends cls_a {
  public void method_a() {
    this.method_a(0);
  }

  public void method_a(int a) {
    //do something for a
    super.method_a();
  }  
}
popcorny
  • 1,710
  • 16
  • 16