如何防止客户端访问基类的公共功能

时间:2013-01-20 05:07:43

标签: java

//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

我想设计cls_b,以便Java编译器在客户端调用b.method_a()时会出错。任何人都知道如何用Java做到这一点?

6 个答案:

答案 0 :(得分:3)

我现在要做的是在method_a()中添加@Deprecated注释(参见下面的示例),因此客户端会收到警告。由于警告很容易被忽略,有没有办法让编译器发出错误?

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();
  }
}

答案 1 :(得分:2)

您不能这样做,因为您无法降低继承方法的可见性(例如,如果它是公开的,则不能将其设为私有)。

Why can't you reduce the visibility of a method in a Java subclass?解释了原因。

答案 2 :(得分:2)

一旦公开,它的范围就可以通过项目获得。无法使特定类隐藏公共功能

更新:我刚刚再次阅读了您的问题。我想你希望其他开发人员从b调用method_a()时会得到异常。如果它是你想要的,那么你可以尝试

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);
    }
}

答案 3 :(得分:1)

您可以这样做:为客户端公开包装类。

 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();
     }
  }

所以现在您的客户应该使用 cls_a_Wrapper 类来代替 cls_a

现在,您可以控制是否要调用基类的公共方法。这是适配器设计模式

如果您不想调用公开方法:

  • 不要在包装器类中提供方法。
  • OR 更改包装类中方法的可见性

记住:对于客户原始类不存在。客户端应将包装类视为基类。

答案 4 :(得分:1)

您不能减少方法在子类中的可见性。

JDK使用UnsupportedOperationException解决了类似的问题,例如:

java.util.Arrays.UnmodifiableCollection

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

java.util.Collection API将此类方法标记为optional operation

boolean add(E e) Ensures that this collection contains the specified element (optional operation).

答案 5 :(得分:0)

防止客户端访问基类的公共功能不是一个好的选择。即使您可以提供运行时异常或已弃用的方法,客户端也可以通过cls_a类型调用您的方法。

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

更好的方法是提供method_a默认实施。对于您的代码,

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();
  }  
}