Я хотел бы ответить на ваш последний вопрос "How to workaround it?"
, так как это не описано в соответствующем вопросе. Создайте второй интерфейс NotDoable
, который просто не имеет doSomething()
. Затем пусть ваш DoJump
реализует оба интерфейса. Дайте всем, кто не должен переопределять doSomething
ссылку на интерфейс NotDoable
вместо истинного типа DoJump
. Тогда они не будут знать, что объект действительно может doSomething
, они не будут знать дизайн каждого класса. Конечно, можно обойти это, но на самом деле можно обойти все. Дизайн класса более правильный. Вот код:
public interface Doable {
public void doSomething();
}
public interface NotDoable {
}
public class DoJump implements Doable, NotDoable {
@Override
public void doSomething() {
System.out.println("hi");
}
public NotDoable meAsNotDoable() {
return this;
}
public static void main(String[] args) {
DoJump object = new DoJump();
// This call is possible, no errors
object.doSomething();
NotDoable hidden = object.meAsNotDoable();
// Not possible, compile error, the true type is hidden!
hidden.doSomething();
}
}
Но, как сказал один может обойти это с помощью if (hidden instanceof DoJump) { DoJump trueObject = (DoJump) hidden; }
. Но хорошо, можно также получить доступ к частным значениям через отражение.
Другие классы теперь реализуют NotDoable
вместо расширения DoJump
. Если вы объявите все, что другие должны знать о DoJump
в этом интерфейсе, тогда они смогут делать то, что должны делать. Вы можете назвать этот интерфейс IDoJump
и реализующим классом DoJump
, общим шаблоном.
Теперь то же самое более конкретное.
public interface IDog {
public void bark();
}
public interface ICanFly {
public void fly();
}
public class FlyingDog implements IDog, ICanFly {
@Override
public void bark() {
System.out.println("wuff");
}
@Override
public void fly() {
System.out.println("Whuiiii");
}
public static void main(String[] args) {
FlyingDog flyingDog = new FlyingDog();
// Both works
flyingDog.fly();
flyingDog.bark();
IDog dog = (IDog) flyingDog;
// Same object but does not work, compile error
dog.fly();
ICanFly canFly = (ICanFly) flyingDog;
// Same object but does not work, compile error
canFly.bark();
}
}
И теперь расширение класса.
public class LoudDog implements IDog {
@Override
public void bark() {
System.out.println("WUUUUFF");
}
// Does not work, compile error as IDog does not declare this method
@Override
public void fly() {
System.out.println("I wanna fly :(");
}
}
В конце концов, быть в курсе, что если другие знают, что их на самом деле IDog
является FlyingDog
(и они бросили его), то они должны быть в состоянии назвать fly()
как FlyingDog
сусло может летать. Кроме того, они должны быть в состоянии переопределить поведение, если они соответствуют спецификации fly()
, указанной его method-signature
. Представьте себе subclass
под названием PoorFlyingDog
, ему нужно переопределить поведение по умолчанию, иначе он может отлично летать, но он бедный летающий.
Подведено: Скрыть для других, что вы на самом деле DoJump
, также скрываете, что вы являетесь Doable
, притворяетесь только NotDoable
. Или с животными, притворяйтесь только IDog
вместо FlyingDog
или ICanFly
. Если другие не делают чит (литье), они не смогут использовать fly()
на вас, хотя вы действительно можете летать.
Вы ищете 'final' , а не 'private'. – Tom
См. Также: [модификаторы java-доступа и методы переопределения] (http://stackoverflow.com/questions/6851612/java-access-modifiers-and-overriding-methods) – Jesper
Вы не можете сделать метод скрытым, как он определен в Интерфейс как открытый. Если вы хотите скрыть его, инкапсулируйте функциональность в новый закрытый метод и вызовите новый метод из метода '' doSomething''. – f1sh