使方法只能访问子类,而不是实例化的对象

时间:2016-03-30 02:51:44

标签: java inheritance

public class Flight{
  private int flying = 0;   
  public boolean fly() {
     flying = 1;
     return isFlying();
  }
  private isFlying(){
    return flying > 0;
  }
}

public class CargoFlight extends Flight{

  public boolean startFlight(int passengers)
    if (passengers <= 0){
      return false;
    }

    return fly(); // Want to be able to do this

  }
}

 public class Airport{
   public static void main(){
     CargoFlight f1 = new CargoFlight();
     f1.fly(); // Don't want to be able to do this
  }
}

f1fly()属性,有没有办法限制它,以便方法fly()可以在扩展类的正文中调用 Flight(如此处CargoFlight),但无法使用子类的实例(如f1)调用?我已经在代码中添加了注释以表明它。

1 个答案:

答案 0 :(得分:5)

您想要的最近的访问说明符是protected。但是,protected成员仍然可以在同一中访问其他类,因此无法阻止Airport类的访问。

如果你确实需要子类来阻止对子类的访问,那么你可以在子类中覆盖它以始终抛出异常,然后使用super来调用原始方法:

public class Flight {
    private int flying = 0;

    protected boolean fly() {
        flying = 1;
        return isFlying();
    }

    private boolean isFlying() {
        return flying > 0;
    }
}

public class CargoFlight extends Flight {
    @Override
    protected boolean fly() {
        throw new IllegalAccessError();
    }

    public boolean startFlight(int passengers) {
        if (passengers <= 0) {
            throw new IllegalArgumentException();
        }

        return super.fly();
    }
}

但是,任何解决方案的缺陷都是违反了Liskov substitution principleCargoFlight不再是Flight的正确实例,因为它没有其他fly具有的正常Flight方法。如果您打算只通过子类调用fly 而直接从不,那么它就可以了(尽管您应该在方法Javadoc中记录该规则) ),但它仍然没有让多态方法调用告知通用Flightfly

一个更好的解决方案,如果它适合您的设计,将flystartFlight是相同的方法(这意味着相同的名称和相同的参数,相同的返回类型或子类型),那么子类方法可以简单地覆盖基础实现。调用者之外的唯一方法是fly。这意味着您的passengers参数也需要成为基本方法Flight.fly的一部分,,从两个方法实现中删除它并将其转换为单独的属性{{ 1}}对于那些需要它的子类:

setPassengers