Ich würde gerne Ihre letzte Frage "How to workaround it?"
beantworten, da dies in der verwandten Frage nicht beschrieben ist. Erstellen Sie eine zweite Schnittstelle NotDoable
, die einfach doSomething()
nicht deklariert hat. Dann lassen Sie Ihre DoJump
beide Schnittstellen implementieren. Geben Sie jedem Benutzer, der doSomething
nicht überschreiben soll, einen Verweis auf die Schnittstelle NotDoable
anstelle des echten Typs DoJump
. Dann werden sie nicht wissen, dass das Objekt wirklich doSomething
, sie pro Klassenentwurf nicht wissen kann. Natürlich kann man das umgehen, aber man kann eigentlich alles umgehen. Das Klassendesign ist auf diese Weise korrekter. Hier einige Code:
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();
}
}
Aber wie gesagt, kann man dies umgehen, indem Sie if (hidden instanceof DoJump) { DoJump trueObject = (DoJump) hidden; }
verwenden. Aber gut, man kann auch über Reflexion auf private Werte zugreifen.
Andere Klassen implementieren jetzt NotDoable
anstatt DoJump
zu erweitern. Wenn Sie in dieser Schnittstelle alles erklären, was andere über DoJump
wissen sollten, dann können sie nur das tun, was sie tun sollten. Sie können diese Schnittstelle IDoJump
und die implementierende Klasse DoJump
ein allgemeines Muster nennen.
Jetzt das gleiche ein bisschen konkreter.
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();
}
}
Und jetzt ein erstreckt Klasse.
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 :(");
}
}
Am Ende bewusst sein, dass, wenn andere wissen, dass ihre IDog
ist eigentlich ein FlyingDog
(und sie es cast), dann müssen sie Lage sein fly()
als FlyingDog
muss fliegen können nennen. Darüber hinaus müssen sie in der Lage sein, das Verhalten zu überschreiben, solange sie der Spezifikation fly()
von method-signature
entsprechen. Stellen Sie sich ein subclass
genannt PoorFlyingDog
vor, er muss das Standardverhalten außer Kraft setzen, sonst kann er perfekt fliegen, aber er ist ein armer Flieger.
Zusammengefasst: Verstecken Sie anderen, dass Sie tatsächlich eine DoJump
sind, auch verstecken, dass Sie eine Doable
sind, so tun, als ob nur eine NotDoable
. Oder mit den Tieren, geben Sie vor, nur eine IDog
anstelle einer FlyingDog
oder ICanFly
zu sein. Wenn die anderen nicht Cheat (Casting), können sie nicht fly()
auf Sie verwenden, obwohl Sie tatsächlich fliegen können.
Sie suchen 'final' nicht "privat". – Tom
Siehe auch: [java access modifiers und overriding methods] (http://stackoverflow.com/questions/6851612/java-access-modifiers-and-overriding-methods) – Jesper
Sie können die Methode nicht verbergen, wie sie in definiert ist die Schnittstelle als öffentlich. Wenn Sie es ausblenden möchten, kapseln Sie die Funktionalität in eine neue private Methode und rufen Sie eine neue Methode von der "doSomething" -Methode auf. – f1sh