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

ECM*_*ipt 4 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
  }
}
Run Code Online (Sandbox Code Playgroud)

f1有属性fly(),有没有办法限制它,这样方法fly()可以在扩展类的体内调用Flight(比如CargoFlight这里),但是不能使用子类实例调用(比如f1)?我已经在代码中添加了注释以表明它.

Boa*_*ann 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,任何解决方案的缺陷都在于它违反了Liskov替代原则.A CargoFlight不再是正确的实例,Flight因为它没有fly其他人拥有的常规方法Flight.如果你fly 打算通过子类调用而不是直接调用,那么它是可以的(尽管你应该在方法Javadoc中记录该规则),但它仍然让你没有使用多态方法来调用告诉泛型Flights fly.

一个更好的解决方案,如果它可以适合您的设计,将具有flystartFlight相同的方法(这意味着相同的名称和相同的参数,以及相同的返回类型或子类型),因此子类方法可以简单地覆盖基础实现.呼叫者会看到的唯一方法是fly.这意味着您的passengers参数也需要成为基本方法的一部分Flight.fly,或者从两个方法实现中删除它,并将其setPassengers作为需要它的那些子类的单独属性:

public class CargoFlight extends Flight {
    private int passengers = 0;

    public void setPassengers(int p) {
        passengers = p;
    }

    @Override
    public boolean fly() {
        if (passengers <= 0) {
            throw new IllegalStateException(); // or whichever
        }

        return super.fly();
    }
}
Run Code Online (Sandbox Code Playgroud)