1

I'm building a little lwjgl library.

I have a RenderController, containing all the render objects AND other objects which are Renderable - so I took an Interface, called Renderable - containing the methods render() and. beforeRenderUpdate(). The problem is: the user of the library shouldn't be allowed to call RenderObject#update, because I want the lib to manage the rendering alone. But I want the user let have instances of this classes, because they sometimes extend AbstractMovableObject, and the user has to move them or request a uniform update. So, the option to create an abstract class containing the render method isn't possible. The advantage of an interfacr would be, I had one list in RenderController, objects <Renderable>(x).render().

But I don't want to have this render method public. What can I do now? As I sad, an abstract class isn't possible because this classes are extending something else.

T_01
  • 1,256
  • 3
  • 16
  • 35

3 Answers3

1

You can take advantage of the I in the SOLID principles, the Interface Segregation Principle.

Use 2 interfaces, one for the public stuff and one for the private stuff. Only expose the object to your user as the public interface. When you need the private methods just cast it to the other interface.

package some.exposed.package;

public interface PublicRenderable {
    public void publicRenderableMethod();
}



package some.package.you.dont.expose;

public interface PrivateRenderable {
    public void privateRenderableMethod();
}

public class RenderObject implements PublicRenderable, PrivateRenderable {
    public void publicRendereableMethod() {
        // implementation
    }

    public void privateRenderableMethod() {
        // implementation
    }
}



package some.exposed.package;    

public class PublicRenderObjectFactory {
    public PublicRenderable getRenderable() {
        return new RenderObject();
    }
}

And your List can be a List<PrivateRenderable>.

Mike B
  • 5,390
  • 2
  • 23
  • 45
  • 1
    Forgive my ignorance, but I don't understand how this solves their issue. If the library users' classes need to be able to have the protected method called on them through polymorphism, how does this help? Also they said that the '_user of the library shouldn't be allowed to call RenderObject#update_', but in your example they still can. – Rudi Kershaw Mar 21 '14 at 14:47
1

Unfortunately there is no way to have protected methods in an interface. All methods in an interface are implicitly public and abstract. Any attempt to deviate from that pattern will not compile.

The following three methods are implicitly identical despite their appearance.

public abstract void doSomething();
public void doSomething();
void doSomething();

If however, you declare anything that explicitly contradicts the above, it will not compile. For example;

protected abstract void doSomething(); // Does not compile
public final void doSomething(); // Does not compile

A simple solution might be to make an abstract class fit the bill somehow. You could try having AbstractMovableObject and your new AbstractRenderableObject class both extend a third class that had this protected update() method (eg AbstractUpdatableObject)? That way they would both BE-A AbstractUpdatableObject, but would otherwise have a very limited relationship (no more than they would if they implemented the same interface) and could even have different implementations of update();.

Rudi Kershaw
  • 12,332
  • 7
  • 52
  • 77
  • I know thats not possible. Someone edited the question title so its not what i mean. But okay, it seems an abstract class is the only way... the problem is, A Renderable Object and a Movable Object shoudlnt have any relationship. That can be different things. But i'll see how to solve this. Thanks. – T_01 Mar 21 '14 at 15:40
  • @T_01 - That's okay. Sorry I couldn't offer a more comprehensive solution. What about having `AbstractMovableObject` and your new `AbstractSomethingObject` class both extend a third class that had this protected update() method (eg `AbstractUpdatableObject`)? That way they would both BE-A `AbstractUpdatableObject`, but would otherwise have a very limited relationship and could even have different implementations of `update();` – Rudi Kershaw Mar 21 '14 at 15:49
1

There is no way to create anything but public functions in an interface.

You can easily implement protected functions in an abstract class, as you've said. You say it's not possible because some of your classes must extend an unrelated class.

So put the protected method into a RenderComposer class, which facilitates composition, so multiple classes can effectively be extended as you wish.

Something like this:

public class RenderComposer  {  //DOES NOT implement Renderable
   public RenderComposer()  {
   }
   public void update_4prot()  {
      //...
   }
}
public class SomeRederMover extends AbstractMovableObject implements Renderable  {
   private final RenderComposer renderer;
   public SomeRederMover()  {
      renderer = new RenderComposer()
   }
   protected void update()  {
      renderer.update_4prot();
   }
}
aliteralmind
  • 19,847
  • 17
  • 77
  • 108
  • and Renderable is an empty Interface, or what? And, how can i differ between differen "SomeRenderMover" ? Because thats not the only renderable class. – T_01 Mar 21 '14 at 15:37
  • If you put `update()` into your interface, then it has to be public. I don't know what other functions belong in your interface, but it seems like `update()` shouldn't be there. The concept in my answer is helpful, for example, in a situation where a helper function is needed internally, but not by *users* of (in my example) `SomeRenderMover`. This part of your question seems to confirm that this is what you want... – aliteralmind Mar 21 '14 at 15:49
  • ..."the user of the library shouldn't be allowed to call RenderObject#update, because I want the lib to manage the rendering alone. But I want the user let have instances of this classes, because they sometimes extend AbstractMovableObject..." – aliteralmind Mar 21 '14 at 15:50