我正在建立一个小的lwjgl库。
我有一个RenderController
,包含所有渲染对象和其他可渲染的对象 - 所以我采用了一个名为Renderable的接口 - 包含方法render()
和。 beforeRenderUpdate()
。
问题是:不应该允许库的用户调用RenderObject#update
,因为我希望lib单独管理渲染。但我希望用户允许拥有此类的实例,因为它们有时会扩展AbstractMovableObject
,并且用户必须移动它们或请求统一更新。
因此,创建包含render方法的抽象类的选项是不可能的。
interfacr
的优势在于,我在RenderController
中有一个列表,对象<Renderable>(x).render()
。
但我不想公开这个渲染方法。我现在能做什么?令我难过的是,抽象类是不可能的,因为这些类正在扩展其他东西。
答案 0 :(得分:1)
您可以利用SOLID principles Interface Segregation Principle中的I
。
使用2个接口,一个用于公共内容,一个用于私有内容。仅将对象公开给用户作为公共接口。当您需要私有方法时,只需将其转换为其他接口。
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();
}
}
您的List
可以是List<PrivateRenderable>
。
答案 1 :(得分:1)
不幸的是,没有办法在接口中使用受保护的方法。界面中的所有方法都是隐式 public
和abstract
。任何偏离该模式的尝试都不会编译。
以下三种方法尽管外观相同但隐含相同。
public abstract void doSomething();
public void doSomething();
void doSomething();
但是,如果您声明任何明显与上述内容相矛盾的内容,则无法编译。例如;
protected abstract void doSomething(); // Does not compile
public final void doSomething(); // Does not compile
一个简单的解决方案可能是让抽象类以某种方式适合该法案。您可以尝试使用AbstractMovableObject
,而您的新AbstractRenderableObject
类都会扩展具有此受保护update()
方法的第三个类(例如AbstractUpdatableObject
)?这样他们就会成为BE-A AbstractUpdatableObject
,但是它们之间的关系非常有限(不会超过他们实现相同界面时的情况),甚至可能有update();
的不同实现。
答案 2 :(得分:1)
在界面中无法创建除公共功能之外的任何内容。
您可以轻松地在抽象类中实现受保护的函数,正如您所说的那样。你说这是不可能的,因为你的一些课程必须扩展一个不相关的课程。
因此,将受保护的方法放入RenderComposer
类,这样可以composition,因此可以根据需要扩展多个类 。
这样的事情:
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();
}
}