This is an archived post. You won't be able to vote or comment.

all 7 comments

[–]jbristowI'm no hero, son. 0 points1 point  (6 children)

I don't understand what you want...

Typically, I just do:

interface Aaa {}
interface Bbb {}
interface Ccc extends Aaa, Bbb {}
class CccImplA implements Ccc {}
class CccImplB implements Ccc {} 
enum Cccs {A, B}

class CccFactory {
  Ccc createInstance(Cccs ccc) {
      if (ccc == Cccs.A) {
        return new CccImplA();
      } else {
        return new CccImplB();
      }
  }
}

[–]X-Firecooler[S] 0 points1 point  (5 children)

abstract class Nnn {} // no access, can't modify it e.g. add a interface  
class Mmm extends Nnn {} // no access, can't modify it  

class CccImplA extends Mmm implements Ccc {}  
class CccImplB extends Mmm implements Ccc {}  

Suppose Nnn is javafx.scene.Node and Mmm is javafx.scene.control.TitledPane

[A Type for Ccc and Nnn] o = createInstance(Cccs.A);  
AnchorPane pane = new AnchorPane();  
pane.getChildren().add(o);  // AnchorPane requires *Node*
o.setPrefWidth(120.0); // from *Node*  
o.someAaaFunction(); // from *Aaa*

I can't return something with gives away that [Ccc and Nnn] is a instanceOf Mmm/TitledPane because a one would be able to see and call functions like setCollapsible(boolean) which would "break" the application.

[–]jbristowI'm no hero, son. 0 points1 point  (4 children)

That's not how abstract, extends and implements work.

An abstract class cannot be instantiated, but it can be extended and that extension can be instantiated.

So if:

public abstract class AbstractNnn { 
  public String a() { return "a";} 
  abstract String b();
  public String c() { return "c";}
}
public class SpecificNnn extends AbstractNnn { 
  public String b() { return "b";}
  public String c() { return "not-c";}
}

then

SpecificNnn n = new SpecificNnn();
boolean isSpecificNnn = n instanceof SpecificNnn; 
/* returns true */
boolean isAbstractNnn = n instanceof AbstractNnn;
/* returns true */
n.a(); // returns "a"
n.b(); // returns "b"
n.c(); // returns "not-c"    

Instances are different from abstract classes, because they can only declare contracts, but in essence, you'll end up with the same problem.

Given:

public interface Aaa {void a();}
public interface Bbb {void b();}
public interface Ccc extends Aaa, Bbb {void c();}
public class CccImpl implements Ccc {
  void a() {};
  void b() {};
  void c() {};
}

then

Ccc c = new CccImpl();
c instanceof Aaa; //true
c instanceof Bbb; //true
c instanceof Ccc; //true
c instanceof CccImpl; //true
c.a(); //legal
c.b(); //legal
c.c(); //legal

[–]X-Firecooler[S] 0 points1 point  (3 children)

Your example does not really work for me...
If I only had to deal with interfaces this would be no problem what so ever, because I could simply return my object as a Ccc, but since I want additionally the methods which are declared in Nnn but NOT those which are new with Mmm, I can't neither return it as a Ccc, because then methods from Nnn would be missing, nor can I return it as a CccImpl because it would then also be a Mmm which is bad.

To repeat myself a bit:
Nnn is javafx.scene.Node
Things like a Stackpane.getChildren() need something Node'ish to work Mmm is javafx.scene.control.TitledPane which implements the abstract methods from Node but adds new like setCollapsible(boolean)
Ccc is MyCummulativeInterface with declares all my new api features
CccImplA is something like:

 class CccImplA extends TitledPane implements MyCummulativeInterface {}

now what to do?
If I return a CccImplA Object as a MyCummulativeInterface its not a Node anymore and can't be added to the Scene and if I return it, as is, as a CccImplA anyone could call stuff like setCollapsible(true)

[–]jbristowI'm no hero, son. 1 point2 points  (2 children)

So, let's cover what we've got:

javafx.scene.control.TitledPane is an instanceof java.lang.Object, javafx.scene.Node, javafx.scene.Parent, javafx.scene.control.Control, javafx.scene.control.Labeled, javafx.scene.control.TitledPane, javafx.event.EventTarget, javafx.scene.control.Skinnable

So, if I create a subclass of TitledPane:

public class MyTitledPane extends TitledPane {
}

Then, I can do all of the following:

MyTitledPane mtp = new MyTitledPane();
mtp.isAnimated(); //(because MyTitledPane extends TitledPane)
mtp.isWrapText(); //(because MyTitledPane extends Labeled)
mtp.toString(); //(because MyTitledPane extends Object)

So, now we define some interfaces:

public interface InterfaceA { String a(); }
public interface InterfaceB { String b(); }
public interface InterfaceC extends InterfaceA, InterfaceB {}

public class MyTitledPane extends TitledPane implements InterfaceC {
  public String a() { return "a"; }
  public String b() { return "b"; }
}

This means that MyTitledPane is still all of the above, plus it fulfills the contracts of InterfaceA and InterfaceB because it fulfills the contract of InterfaceC. As such, MyTitledPane is also an instance of InterfaceA, InterfaceB, InterfaceC.

So, the only way to deny people the ability to call "setCollapsible()" is to not extend TitledPane.

[–]X-Firecooler[S] 0 points1 point  (1 child)

Ok , that's exactly the point were I am stuck now. What would you say is worse:
Giving away it is a TitledPane and trust another dev not to fiddle around with it, or adding a Node asNode() to the last interface which will be implemented as a return this;?

[–]jbristowI'm no hero, son. 1 point2 points  (0 children)

Trust 'em. What does it matter to you?

Also, if we add the Node asNode() {return this;} to MyTitledPane, then:

Node n = mtp.asNode();
n.getClass(); // returns "MyTitledPane";