Am I using a feature of Java 8 or misusing it?
Refer the code and explanation below to know as to why it was chosen to be like this.
public interface Drawable {
public void compileProgram();
public Program getProgram();
default public boolean isTessellated() {
return false;
}
default public boolean isInstanced() {
return false;
}
default public int getInstancesCount() {
return 0;
}
public int getDataSize();
public FloatBuffer putData(final FloatBuffer dataBuffer);
public int getDataMode();
public boolean isShadowReceiver();
public boolean isShadowCaster(); //TODO use for AABB calculations
default public void drawDepthPass(final int offset, final Program depthNormalProgram, final Program depthTessellationProgram) {
Program depthProgram = (isTessellated()) ? depthTessellationProgram : depthNormalProgram;
if (isInstanced()) {
depthProgram.use().drawArraysInstanced(getDataMode(), offset, getDataSize(), getInstancesCount());
}
else {
depthProgram.use().drawArrays(getDataMode(), offset, getDataSize());
}
}
default public void draw(final int offset) {
if (isInstanced()) {
getProgram().use().drawArraysInstanced(getDataMode(), offset, getDataSize(), getInstancesCount());
}
else {
getProgram().use().drawArrays(getDataMode(), offset, getDataSize());
}
}
default public void delete() {
getProgram().delete();
}
public static int countDataSize(final Collection<Drawable> drawables) {
return drawables.stream()
.mapToInt(Drawable::getDataSize)
.sum();
}
public static FloatBuffer putAllData(final List<Drawable> drawables) {
FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(countDataSize(drawables) * 3);
drawables.stream().forEachOrdered(drawable -> drawable.putData(dataBuffer));
return (FloatBuffer)dataBuffer.clear();
}
public static void drawAllDepthPass(final List<Drawable> drawables, final Program depthNormalProgram, final Program depthTessellationProgram) {
int offset = 0;
for (Drawable drawable : drawables) {
if (drawable.isShadowReceiver()) {
drawable.drawDepthPass(offset, depthNormalProgram, depthTessellationProgram);
}
offset += drawable.getDataSize(); //TODO count offset only if not shadow receiver?
}
}
public static void drawAll(final List<Drawable> drawables) {
int offset = 0;
for (Drawable drawable : drawables) {
drawable.draw(offset);
offset += drawable.getDataSize();
}
}
public static void deleteAll(final List<Drawable> drawables) {
drawables.stream().forEach(Drawable::delete);
}
}
public interface TessellatedDrawable extends Drawable {
#Override
default public boolean isTessellated() {
return true;
}
}
public interface InstancedDrawable extends Drawable {
#Override
default public boolean isInstanced() {
return true;
}
#Override
public int getInstancesCount();
}
public class Box implements TessellatedDrawable, InstancedDrawable {
//<editor-fold defaultstate="collapsed" desc="keep-imports">
static {
int KEEP_LWJGL_IMPORTS = GL_2_BYTES | GL_ALIASED_LINE_WIDTH_RANGE | GL_ACTIVE_TEXTURE | GL_BLEND_COLOR | GL_ARRAY_BUFFER | GL_ACTIVE_ATTRIBUTE_MAX_LENGTH | GL_COMPRESSED_SLUMINANCE | GL_ALPHA_INTEGER | GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH | GL_ALREADY_SIGNALED | GL_ANY_SAMPLES_PASSED | GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH | GL_ACTIVE_PROGRAM | GL_ACTIVE_ATOMIC_COUNTER_BUFFERS | GL_ACTIVE_RESOURCES | GL_BUFFER_IMMUTABLE_STORAGE;
int KEEP_OWN_IMPORTS = UNIFORM_PROJECTION_MATRIX.getLocation() | VS_POSITION.getLocation();
}
//</editor-fold>
private FloatBuffer data;
private Program program;
private final float width, height, depth;
public Box(final float width, final float height, final float depth) {
this.width = width;
this.height = height;
this.depth = depth;
data = generateBox();
data.clear();
}
#Override
public void compileProgram() {
program = new Program(
new VertexShader("data/shaders/box.vs.glsl").compile(),
new FragmentShader("data/shaders/box.fs.glsl").compile()
).compile().usingUniforms(
UNIFORM_MODEL_MATRIX,
UNIFORM_VIEW_MATRIX,
UNIFORM_PROJECTION_MATRIX,
UNIFORM_SHADOW_MATRIX
);
}
#Override
public int getInstancesCount() {
return 100;
}
#Override
public Program getProgram() {
return program;
}
#Override
public int getDataSize() {
return 6 * 6;
}
#Override
public FloatBuffer putData(final FloatBuffer dataBuffer) {
FloatBuffer returnData = dataBuffer.put(data);
data.clear(); //clear to reset data state
return returnData;
}
#Override
public int getDataMode() {
return GL_TRIANGLES;
}
#Override
public boolean isShadowReceiver() {
return true;
}
#Override
public boolean isShadowCaster() {
return true;
}
private FloatBuffer generateBox() {
FloatBuffer boxData = BufferUtils.createFloatBuffer(6 * 6 * 3);
//put data into boxData
return (FloatBuffer)boxData.clear();
}
}
First the steps on how I came to this code:
I started with the Drawable interface and each implementation having its own drawDepthPass, draw and delete methods.
Refactoring delete to a default method was easy, trivial and should not be wrong.
However to be able to refactor drawDepthPass and draw I needed access to whether a Drawable was tesselated and/or instanced, so I added the public (non-default) methods isTessellated(), isInstanced() and getInstancesCount().
Then I figured out it would be slightly cumbersome, as we programmers are lazy, to implement them in every Drawable.
As a consequence I added the default methods to Drawable, giving the behaviour of the most basic Drawable.
Then I figured that I am still lazy and do not want to manually implement it for the tessellated and instanced variants eithere.
So I created TessellatedDrawable and InstancedDrawable that provide default isTessellated() and isInstanced() respectively. And in InstancedDrawable I revoked the default implementation of getInstancesCount().
As a result I can have the following:
Normal Drawable: public class A implements Drawable
Tessellated Drawable: public class A implements TessellatedDrawable
Instanced Drawable: public class A implements InstancedDrawable
Tessellated and instanced Drawable: public class A implements InstancedDrawable, TessellatedDrawable.
Just to ensure you, this all compiles and runs fine, the implements InstancedDrawable, TessellatedDrawable gets handled perfectly by Java 8 as there is nowhere ever ambiguity on from which interface the functionality should come.
Now onto my own little OOP design assessment:
Every Drawable is in fact a Drawable, so Collection<Drawable> will not break.
It is possible to group all TessellatedDrawable and/or InstancedDrawable, irrelevant of how exactly it is implement.
Other thoughts I had:
Use a more conventional, layered approach, however I disregarded that as it would end up in:
abstract class AbstractDrawable
class Drawable extends AbstractDrawable
class TessellatedDrawable extends AbstractDrawable
class InstancedDrawable extends AbstractDrawable
class InstancedTessellatedDrawable extends AbstractDrawable
I have also considered a Builder Pattern, however that is a pattern to be used when you are creating a lot of unique instances of a certain object, and that is not what we are doing here, neither is this about the constructor of the object.
So the first and final question was: Am I using a feature of Java 8 or misusing it?
First, if it works, and it does what you want to do, and there's no danger of something breaking in the future, it doesn't make sense to say you're misusing it. After all, it got the job done, right? Features like default methods and static methods were added to interfaces with particular goals in mind, but if they help you achieve other goals, either that's creative use of a new feature or a gross and dirty hack. :-) To a certain extent it's a matter of taste.
With that perspective in mind, what I look for in APIs, and what I try to do when designing APIs, is to distinguish clients of an API from implementors of an API. A typical client, or user, of an API gets a reference of some interface type from somewhere and calls methods on it to make stuff happen. An implementor provides implementations for methods defined in interfaces, overrides methods, and (if subclassing) calls superclass methods. Often, the methods intended to be called by clients are different from those intended to be called from subclasses.
It seems to me that these concepts are being mixed in the Drawable interface. Certainly, clients of a Drawable will do things like call the draw or drawDepthPass methods on them. Great. But looking at the default implementation of drawDepthPass, it gets some information using isTessellated and isInstanced methods, and then uses these to choose a Program and call methods on it in a particular way. It's fine for these bits of logic to be encapsulated within a method, but in order for it to be done in a default method, the getters have to be forced into the public interface.
I might be wrong about your model, of course, but it seems to me that this kind of logic is more suited for an abstract superclass and subclasser relationship. The abstract superclass implements some logic that handles all Drawables, but it negotiates with the particular Drawable implementations with methods like isTesselated or isInstanced. In an abstract superclass, these would be protected methods that subclasses are required to implement. By putting this logic into default methods of an interface, all of these have to be public, which clutters up the client interface. The other methods that seem similar are getDataMode, isShadowReceiver, and isShadowCaster. Are clients expected to call these, or are they logically internal to the implementation?
What this highlights is that, despite the addition of default methods and static methods, interfaces are still oriented toward clients, and less toward supporting subclasses. The reasons are as follows:
Interfaces have only public members.
Abstract classes can have protected methods for subclasses to override or call.
Abstract classes can have private methods to enable implementation sharing.
Abstract classes can have fields (state) which can be protected to share state with subclasses, or usually private otherwise.
Abstract classes can have final methods that enforce certain behavior policies on subclasses.
Another issue I note with the Drawable interface family is that it uses the ability of default methods to override each other to allow some simple mixins to the implementation classes like Box. It is kind of neat that you can just say implements TessellatedDrawable and avoid the pesky overriding of the isTesselated method! The problem is that this now becomes part of the implementation class's type. Is it useful for the client to know that a Box is also a TessellatedDrawable? Or is this just a scheme for making the internal implementation cleaner? If it's the latter, it might be preferable these mixin interfaces like TessellatedDrawable and InstancedDrawable not be public interfaces (i.e., package private).
Note also that this approach clutters up the type hierarchy, which can make code more confusing to navigate. Usually a new type is a new concept, but it seems heavyweight to have interfaces that merely define default methods returning boolean constants.
A further point in this vein. Again, I don't know your model, but the characteristics being mixed in here are very simple: they're just boolean constants. If there's ever a Drawable implementation that, say, starts off not being instanced and later can become instanced, it can't use these mixin interfaces. The default implementations are really quite restricted in what they can do. They can't call private methods or inspect fields of an implementation class, so their use is quite limited. Using interfaces this way is almost like using them as marker interfaces, with a tiny addition of being able to call a method to get the characteristic, instead of using instanceof. There doesn't seem to be much use beyond this.
The static methods in the Drawable interface seem mostly reasonable. They're utilities that seem client-oriented, and they provide reasonable aggregations of logic provided by the public instance methods.
Finally, there are a few points about the model that seem odd, though they're not directly related to the use of default and static methods.
It seems like a Drawable has-a Program, as there are instance methods compileProgram, getProgram, and delete. Yet the drawDepthPass and similar methods require the client to pass in two programs, one of which is selected depending on the result of the boolean getters. It's not clear to me where the caller is supposed to choose the right Programs.
Something similar is going on with the drawAll methods and the offset value. It seems like in a list of Drawables, they have to be drawn using particular offsets based on each Drawable's data size. Yet what is apparently the most fundamental method, draw, requires the caller to pass in an offset. This seems like a big responsibility to push onto the caller. So perhaps the offset stuff really belongs within the implementation as well.
There are a couple methods that take a List of drawables and call stream() and then forEach() or forEachOrdered(). This isn't necessary, as List has a forEach method on it, inherited from Iterable.
I think it's great to explore how this new stuff can be used. It's new enough that a commonly accepted style hasn't yet emerged. Experiments like this, and this discussion, help to develop that style. On the other hand, we also need to be careful not to use these shiny new features just because they're new and shiny.
Related
I have a Java class that has some private variable that I don't intend to create setters and getters for; I want these variables to remain inaccessible. But there is one class that needs access to these variables. This class is a visitor in a different package (and I'd prefer to keep it in a different package). Is it bad practice to allow this class to provide the visitor with Consumers and Suppliers, that act as setters and getters, so that the visitor could read and modify these variables? If yes, please state the reasons.
Example:
A.java
public class A {
private int x;
private Consumer<Integer> setter;
private Supplier<Integer> getter;
public A(int v) {
x = v;
setter = new Consumer<Integer>() {
#Override
public void accept(Integer t) {
x = t;
}
};
getter = new Supplier<Integer>() {
#Override
public Integer get() {
return x;
}
};
}
public void accept(SomeVisitor visitor) {
visitor.setSetter(setter);
visitor.setGetter(getter);
visitor.visit(this);
}
}
SomeVisitor.java
public class SomeVisitor extends ParentVisitor {
private Consumer<Integer> setter;
private Supplier<Integer> getter;
public SomeVisitor() {
setter = null;
getter = null;
}
public void setSetter(Consumer<Integer> setter) {
this.setter = setter;
}
public void setGetter(Supplier<Integer> getter) {
this.getter = getter;
}
#Override
public void visit(A a) {
// Code that will, possibly, read and modify A.x
...
}
}
This way the variable A.x remains inaccessible to every class except the visitor.
More Details:
I have some classes that will make use of the visitors. These classes have private variables that are dependent on one another. If these variables had setters, inconsistencies could arise as users change these variables, that should be dependent on one another, without respecting these dependecies.
Some of these variables will have getters, others won't as they will only be used internally and shouldn't be accessed elsewhere. The reason the visitors are an exception and should get read/write access to these variables is that the functionality the visitors are intended to implement were meant to be implemented within methods in these classes. But I thought it will be cleaner if I used visitors. And these functionalities do need read/write access to these variables.
The intention behind this approach was to emulate the friend feature in C++. I could place the visitors within the same package as these classes (which I would do if I didn't find a neat solution to this problem); But I think the package will look messy if it had the visitors as well (and there will be many visitors).
The functionality the visitors will implement will also have something to do with these classes relations to one another.
I tried to squeeze it into a comment, as it technically does not answer the question about whether this is a "Bad Practiceâ„¢", but this term is hard to define, and thus, it is nearly impossible to give an answer anyhow...
This eventually seems to boil down to the question of how to Make java methods visible to only specific classes (and there are similar questions). The getter/setter should only be available to one particular class - namely, to the visitor.
You used very generic names and descriptions in the question, and it's hard to say whether this makes sense in general.
But some points to consider:
One could argue that this defeats the encapsulation in general. Everybody could write such a visitor and obtain access to the get/set methods. And even though this would be a ridiculous hack: If people want to achieve a goal, they will do things like that! (sketeched in Appendix 1 below)
More generally, one could argue: Why is only the visitor allowed to access the setter/getter, and other classes are not?
One convincing reason to hide getter/setter methods behind Supplier/Consumer instances could be related to visibility and the specificness of classes (elaborated in Appendix 2). But since the visitor always has the dependency to the visited class, this is not directly applicable here.
One could argue that the approach is more error prone. Imagine the case that either the setter or the getter are null, or that they belong to different instances. Debugging this could be awfully hard.
As seen in the comments and other answer: One could argue that the proposed approach only complicates things, and "hides" the fact that these are actually setter/getter methods. I wouldn't go so far to say that having setter/getter methods in general already is a problem. But your approach is now to have setter-setters and getter-setters in a visitor. This extends the state space of the visitor in a way that is hard to wrap the head around.
To summarize:
Despite the arguments mentioned above, I would not call it a "bad practice" - also because it is not a common practice at all, but a very specific solution approach. There may be reasons and arguments to do this, but as long as you don't provide more details, it's hard to say whether this is true in your particular case, or whether there are more elegant solutions.
Update
For the added details: You said that
inconsistencies could arise as users change these variables
It is usually the responsibility of a class to manage its own state space in a way that makes sure that it is always "consistent". And, in some sense, this is the main purpose of having classes and encapsulation in the first place. One of the reasons of why getters+setters are sometimes considered as "evil" is not only the mutability (that should usually be minimized). But also because people tend to expose properties of a class with getters+setters, without thinking about a proper abstraction.
So specifically: If you have two variables x and y that depend on one another, then the class should simply not have methods
public void setX(int x) { ... }
public void setY(int y) { ... }
Instead, there should (at best, and roughly) be one method like
public void setState(int x, int y) {
if (inconsistent(x,y)) throw new IllegalArgumentException("...");
...
}
that makes sure that the state is always consistent.
I don't think that there is a way of cleanly emulating a C++ friend function. The Consumer/Supplier approach that you suggested may be reasonable as a workaround. Some (not all) of the problems that it may cause could be avoided with a slightly different approach:
The package org.example contains your main class
class A {
private int v;
private int w;
public void accept(SomeVisitor visitor) {
// See below...
}
}
And the package org.example also contains an interface. This interface exposes the internal state of A with getter+setter methods:
public interface InnerA {
void setV(int v);
int getV();
void setW(int w);
int getW();
}
But note that the main class does not implement this interface!
Now, the visitors could reside in a different packakge, like org.example.visitors. And the visitor could have a dedicated method for visiting the InnerA object:
public class SomeVisitor extends ParentVisitor {
#Override
public void visit(A a) {
...
}
#Override
public void visit(InnerA a) {
// Code that will, possibly, read and modify A.x
...
}
The implementation of the accept method in A could then do the following:
public void accept(SomeVisitor visitor) {
visitor.accept(this);
visitor.accept(new InnerA() {
#Override
public void setX(int theX) {
x = theX;
}
#Override
public int getX() {
return x;
}
// Same for y....
});
}
So the class would dedicatedly pass a newly created InnerA instance to the visitor. This InnerA would only exist for the time of visiting, and would only be used for modifying the specific instance that created it.
An in-between solution could be to not define this interface, but introduce methods like
#Override
public void visit(Consumer<Integer> setter, Supplier<Integer> getter) {
...
}
or
#Override
public void visit(A a, Consumer<Integer> setter, Supplier<Integer> getter) {
...
}
One would have to analyze this further depending on the real application case.
But again: None of these approaches will circumvent the general problem that when you provide access to someone outside of your package, then you will provide access to everyone outside of your package....
Appendix 1: A class that is an A, but with public getter/setter methods. Goodbye, encapsulation:
class AccessibleA extends A {
private Consumer<Integer> setter;
...
AccessibleA() {
EvilVisitor e = new EvilVisitor();
e.accept(this);
}
void setSetter(Consumer<Integer> setter) { this.setter = setter; }
...
// Here's our public setter now:
void setValue(int i) { setter.accept(i); }
}
class EvilVisitor {
private AccessibleA accessibleA;
...
public void setSetter(Consumer<Integer> setter) {
accessibleA.setSetter(setter);
}
...
}
Appendix 2:
Imagine you had a class like this
class Manipulator {
private A a;
Manipulator(A a) {
this.a = a;
}
void manipulate() {
int value = a.getValue();
a.setValue(value + 42);
}
}
And now imagine that you wanted to remove the compile-time dependency of this class to the class A. Then you could change it to not accept an instance of A in the constructor, but a Supplier/Consumer pair instead. But for a visitor, this does not make sense.
As getters and setters are evil anyway, you'll be better off making things not more complicated than ordinary getters and setters.
I design my game application and face some troubles in OOP design.
I want to know some patterns which can help me, because java have not any multiple extends option. I will describe my problem below, and also explain why multiple interface doesn't help me at all. Lets go.
What we want is "class is set of features". By feature I mean construction like:
field a;
field b;
field c;
method m1(){
// use, and change fields a,b,c;
}
method m2(){
// use, and change fields a,b,c;
}
//etc
So, basically the feature is a set of methods and corresponding fields. So, it's very close to the java interface.
When I talk that class implemets "feature1" I mean that this class contains ALL "feature needed" fields, and have realisation of all feature related methods.
When class implements two features the tricky part begins. There is a change, that two different features contains similar fields (names of this fields are equal). Let the case of different types for such fields will be out of scope. What I want - is "feature naming tolerance" - so that if methodA() from feature A change the field "common_field", the methodB from feature B, that also use "common_field" as field will see this changes.
So, I want to create a set of features (basically interfaces) and their implementations. After this I want to create classes which will extends multiple features, without any copy-paste and other crap.
But I can't write this code in Java:
public static interface Feature1 {
public void method1();
}
public static interface Feature2 {
public void method2();
}
public static class Feature1Impl implements Feature1 {
int feature1Field;
int commonField;
#Override
public void method1() {
feature1Field += commonField;
commonField++;
}
}
public static class Feature2Impl implements Feature2 {
int feature2Field;
int commonField;
#Override
public void method2() {
commonField++;
}
}
public static class MyFeaturedClass extends Feature1Impl, Feature2Impl implements Feature1, Features2 {
}
So, as you can see the problem are really complex.
Below I'll describe why some standart approaches doesn't work here.
1) Use something like this:
public static class MyFeaturesClass implements Feature1,Feature2{
Feature1 feature1;
Feature2 feature2;
#Override
public void method2() {
feature2.method2();
}
#Override
public void method1() {
feature1.method1();
}
}
Ok, this is really nice approach - but it does not provide "feature field name tolerance" - so the call of method2 will not change the field "commonField" in object corresponding the feature1.
2) Use another design. For what sake you need such approach?
Ok. In my game there is a "unit" concept. A unit is MOVABLE and ALIVE object.
Movable objects has position, and move() method. Alive objects has hp and takeDamage() and die() methods.
There is only MOVABLE objects in my game, but this objects isn't alive.
Also, there is ALIVE objects in my game, but this objects isn't movable (buildings for example).
And when I realize the movable and alive as classes, that implements interfaces, I really don't know from what I should extends my Unit class. In both cases I will use copy-paste for this.
The example above is really simple, actually I need a lot of different features for different game mechanics. And I will have a lot of different objects with different properties.
What I actually tried is:
Map<Field,Object> fields;
So any object in my game has such Map, and to any object can be applied any method. The realization of method is just take needed fields from this map, do its job and change some of them. The problem of this approach is performance. First of all - I don't want to use Double and Interger classes for double and int fields, and second - I want to have a direct accsess to the fields of my objects (not through the map object).
Any suggestions?
PS. What I want as a result:
class A implements Feature1, Feature2, Feature3, Feature4, Feature5 {
// all features has corresponding FeatureNImpl implementations;
// features 1-2-3 has "shared" fields, feature 3-4 has, features 5-1 has.
// really fast implementation with "shared field tolerance" needed.
}
One possibility is to add another layer of interfaces. XXXProviderInterface could be defined for all possible common fields, that define a getter and setter for them.
A feature implementation class would require the needed providers in the constructor. All access to common fields are done through these references.
A concrete game object class implementation would implement the needed provider interfaces and feature interfaces. Through aggregation, it would add the feature implementations (with passing this as provider), and delegate the feature calls to them.
E.g.
public interface Feature1 {
void methodF1();
}
public interface Feature2 {
void methodF2();
}
public interface FieldAProvider {
int getA();
void setA(int a);
}
public class Feature1Impl implements Feature1 {
private FieldAProvider _a;
Feature1Impl(FieldAProvider a) {
_a = a;
}
void methodF1() {
_a.setA(_a.getA() * 2);
}
}
// Similar for Feature2Impl
public class GameObject implements Feature1, Feature2, FieldAProvider
{
int _fieldA;
Feature1 _f1;
Feature2 _f2;
GameObject() {
_f1 = new Feature1Impl(this);
_f2 = new Feature2Impl(this);
}
int getA() {
return _fieldA;
}
void setA(int a) {
_fieldA = a;
}
void methodF1() {
_f1.methodF1();
}
void methodF2() {
_f2.methodF2();
}
}
However, I don't think this is an optimal solution
I am using the Processing.org api - so i cant just change the classes in question.
Problem is simple, but i havent found an answer:
void drawStuff(PGraphics view) {
view.beginShape();
view.vertex(... lots of vertex calls / lines
}
void drawStuff(PShape view) {
view.beginShape();
view.vertex(... lots of vertex calls / lines
}
what i need is a way to combine them into one method, like:
void drawStuff(Object view) {
// how to cast to PShape and PGraphics
view.beginShape();
view.vertex(... lots of vertex calls /lines
}
the classes PShape and PGraphics have same/similar methods, at lest for the one i call, they are the same. But according to the Processing javadocs, PShape and PGraphics are both coming from java.lang.Object, so as far as i understand the dont share anything.
Like others pointed out in the comments of the OP, write a wrapper class/interface. The interface is the abstraction towards your code in which you don't want to know the actual implementation you're dealing with:
Start with defining the interface:
public interface PWrapper {
public void beginShape();
public void vertex();
}
Then, because of the unfortunate design in which PShape and PGraphics have nothing in common but Object, you'll need to implement a wrapper for each of these classes that implements your new interface. These wrappers are infact delegating their method calls to the appropriate methods of the wrapped object. For example, the wrapper for a PShape would be implemented like this:
public final class PShapeWrapper implements PWrapper {
private final PShape ps;
public PShapeWrapper (PShape ps){
this.ps = ps;
}
#Override
public void beginShape(){
ps.beginShape();
}
#Override
public void vertex(){
ps.vertex();
}
}
Then again in your code, define the method like this:
void drawStuff(PWrapper wrap) {
wrap.beginShape();
wrap.vertex();
}
As you can see, this method does not know what runtime object it's dealing with: it may be a PShapeWrapper (see above) or a PGraphicsWrapper (not posted). Even better: it may be any class that implements PWrapper but doesn't exist yet, so this is a maintainability plus.
This design pattern is called "Adapter".
I was reading some article about collision avoidance systems in cars when my programmer mind led me to think of that concept in the object-oriented way, and it made me wonder if those systems respect the object-oriented programming model.
Being mainly a Java developer, I transposed this problem in a Java environment and it raised a particular question: does calling a public method within the same class (in a non-static context) respect and follow the object-oriented way?
I mean, take this brief hypothetical Car class:
public class Car {
// Class attributes.
// Constructors.
public void accelerate(final double amplitude) {
// Accelerate according to the amplitude.
}
public void brake(final double amplitude) {
// Brake according to the amplitude.
}
// Other useful methods.
private void collisionPreventionActions() {
// Some actions.
brake(100.0);
// Some other actions.
}
}
Suppose some Thread is responsible of detecting a collision and take actions when it does detect a collision, and one of those actions would be braking. Obviously the brake(...) method becomes an interesting choice, but doesn't that break the object-oriented way of doing things? It's not just the brakes though. What if the collision avoidance system in this class used the steering wheel instead to avoid the accident? I find it weird that the car would be using its own input from an internal point of view...
On a more general scope, suppose you have a generic object, which I like to see as a black box. The public methods would be the equivalent of levers on that black box that would control its behaviour. Calling a public method within this object would mean that the black box would activate its own levers from its internal mechanism.
I ask because I know it's legal in Java to do so, and that I've seen public methods being called within the same class numerous times in my life, but it being legal doesn't necessarily mean that it's the proper OO way of doing it.
Does using public methods within the same class in a non-static context follow the rules of object-oriented programming and encapsulation? If not, what would be the proper way of doing it or what could be the workaround?
There is nothing wrong with this choice from the OOP perspective: it is perfectly fine for a method to perform things that require combinations of other methods.
In practice, though, a common approach would be to separate the functionality into a public and a private portions, like this:
public void brake(final double amplitude) {
// check preconditions
if (speed == 0) throw new IllegalStateException("cannot brake when standing");
if (amplitude <= 0) throw new IllegalArgumentException("amplitude must be positive");
// ... do other important checks
doBrake(amplitude);
}
private void doBrake(final double amplitude) {
// The real code goes here
}
Now your collisionPreventionActions could call doBrake instead of brake, assuming that you have checked all the necessary preconditions before making the call.
Note: doBrake should check its preconditions as well. However, rather than throwing exceptions when preconditions are not met, it can use assertions. The difference is that exceptions indicate a misuse of your public methods by others, while assertions indicate misuse of your encapsulated methods by you or someone else maintaining your code.
No rules are violated when an object uses its own API. On the contrary, problems are likely to occur if a class has an API that can be overridden, but it fails to use that API internally.
As a trivial example, consider a non-final property accessor. An object could skip the accessor and read (or worse, write) fields directly. Suppose the accessor is overridden in a subclass to compute the property value using the field together with some other information from the subclass. Now the class is broken because it failed to honor its own contract.
Consider the (somewhat contrived) Point and OffsetPoint classes below. The derived class, OffsetPoint is written correctly, but it's inherited toString() method will not work as expected because the parent class, Point, wrongly fails to use its own accessors.
public class Point {
private final int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; }
public int getY() { return y; }
#Override
public final String toString() {
/* Here's the bug; should be getX() and getY() instead of x and y */
return String.format("(%d,%d)", x, y);
}
}
class OffsetPoint extends Point {
private int dx, dy;
OffsetPoint(Point point, int dx, int dy) {
super(point.getX(), point.getY());
this.dx = dx;
this.dy = dy;
}
#Override
public int getX() { return super.getX() + dx; }
#Override
public int getY() { return super.getY() + dy; }
}
Does using public methods within the same class in a non-static context follow the rules of object-oriented programming and encapsulation?
No, there is no problem with encapsulation becuase the method is public so anyone (even this) can call it.
However, for something like a collision avoidance system, relying on public methods could be bad security wise.
Let's use your example of this intenal Collision detector calling the public method brake(). What if someone subclassed car and overrode the method?
public class BrokenCar extends Car{
#Override
public void brake(final double amplitude) {
//BREAKS CUT!!!
}
}
So there are some security rules of not relying on overridable methods. Making brake and accelerate final methods resolves this problem.
Yes, I think it is proper in an OO context to call your own public method. It's quite common when there are overloads for a method that all but one call the most specific one, either filling in defaults for missing parameters or transforming the type of the argument(s). I also see the pattern where all the overloads call into a private or protected method of the same name with _internal or _impl added to the end. For example, several overloads of ComputeSpeed might all call ComputerSpeed_internal. This pattern would be appropriate if there is parameter validation in the public methods that you don't want to do twice, or would be inappropriate for internal calls.
You can certainly introduce problems by not having a clear separation of concerns. For example, if the caller of collisionPreventionActions also decided it was a good idea to set the brake, you could have a conflict in how much brake is applied.
KC
In general, it is fine to call the public methods. The thing to consider is what the interface of the Car should be. In this case, does preventCollision() belong in the Car class or in some other CollisionPrevention class.
Breaking your code multiple classes each with a single responsibility, and then using them a bigger class like Car, is generally a good idea.
I totally agree with you that it's common that a class itself addresses its private members and methods. But I don't understand why it shouldn't be legal in terms of the Object Oriented Paradigm. Consider the following example:
public class Human {
public Human() {
liveYourLife();
}
private void liveYourLife() {
while(alive){
createYourDay();
}
}
private void createYourDay() {
drink();
eat();
sleep();
awake();
drink();
}
private void eat() {}
private void drink() {}
private void sleep() {}
private void awake() {}
}
Probably someone will criticise the simple rule of life, shown in the example above. But what I want to demonstrate with the few lines above is, that "normally" a human is allowed to decide on his daily routine.
The basic principle of the OO-Paradigm is to describe the actions and properties of real world entities. Hence, as long you are allowed to yourself decide on when you want to eat, drink, sleep, etc. your above described model is absolutely correct. But if you discover some exceptional cases in your problem domain which you want to address in your software (e.g. you got arrested, etc. ) you should update your OO-design.
In case that there is an something, which heavily influences the state of another instance, you should treat that "instance of disturbance" as a different object which has a reference to the actual instance.
public class Prisoner extends Human {
#Override
private void liveYourLife() {
while(jailed){
createYourDay();
}
}
#Override
private void createYourDay() {
// A bit different :)
}
}
public class Prison {
private List<Prisoner> prisoners;
}
These functions may be hard to fit into a specific class,
what's the best practice to deal with them?
I suppose you mean methods instead of functions? You should really imagine the word static doesn't exist in Java world, there really isn't a case where static would actually do you anything good in the long run.
I'm actually currently facing a similar problem, I have a whole bunch of API methods I want to give out for users to meddle with but I want to hide the actual methods underneath to hide the implementation details.
The problem of course is that if I just cram everything into one class, it becomes humongous and hard to use even with the best autocompletion tools available. The problem you have most likely really isn't about where to put those methods but how to present them to the user.
To solve that I'd suggest you create a hierarchy of objects where you access your helper methods by calling myUtil.someGroup().someMethod(param1, param2); This is actually how some API:s already work, for example popular Web framework Apache Wicket is configured by using Settings object which uses composition to allow itself to have multiple groups of distinct features.
To really flesh out this from theory to a working example, lets assume you have a bunch of image manipulation methods which either transform the image's dimensions or change its properties like color, brightness and contrast. Instead of having this:
public class ImageUtil {
public static BufferedImage adjustHue(float difference,
BufferedImage original) {
/* ... */
return adjusted;
}
public static BufferedImage adjustBrightness(float difference,
BufferedImage original) {
/* ... */
return adjusted;
}
public static BufferedImage adjustContrast(float difference,
BufferedImage original) {
/* ... */
return adjusted;
}
public static BufferedImage setHeight(int newHeight,
BufferedImage original) {
/* ... */
return adjusted;
}
public static BufferedImage setWidth(int newWidth,
BufferedImage original) {
/* ... */
return adjusted;
}
}
you should instead have these interfaces to describe each set of operations:
public interface IImageColorOperations {
BufferedImage adjustHue(float difference, BufferedImage original);
BufferedImage adjustBrightness(float difference, BufferedImage original;)
BufferedImage adjustContrast(float difference, BufferedImage original);
}
public interface IImageDimensionOperations {
BufferedImage setHeight(int newHeight, BufferedImage original);
BufferedImage setWidth(int newWidth, BufferedImage original);
}
and an accompanying separate class for each interface which you instantiate in your "main" image utility class like so:
public class ImageUtils {
private final IImageDimensionOperations dimension;
private final IImageColorOperations color;
public ImageUtils() {
this(new ImageDimensionOperations(),
new ImageColorOperations());
}
/**
* Parameterized constructor which supports dependency injection, very handy
* way to ensure that class always has the required accompanying classes and
* this is easy to mock too for unit tests.
*/
public ImageUtils(IImageDimensionOperations dimension,
IImageColorOperations color) {
this.dimension = dimension;
this.color = color;
}
/* utility methods go here */
}
But wait, this isn't all! There's now two paths to go, you can decide for yourself which one you'd like to take.
First, you can use composition to expose the interface methods directly:
public class ImageUtils implements IImageDimensionOperations,
IImageColorOperations {
private final IImageDimensionOperations dimension;
private final IImageColorOperations color;
public ImageUtils() {
this(new ImageDimensionOperations(),
new ImageColorOperations());
}
/* etc. */
}
With this, you just need to delegate the calls to various methods to the actual operation class. Downside to this is that if you add another method, you have to modify both this utility class and the underlying implementation class.
Your second choice is to expose the operation classes themselves directly (that's why I added those finals there!):
public class ImageUtils {
public final IImageDimensionOperations dimension;
public final IImageColorOperations color;
public ImageUtils() {
this(new ImageDimensionOperations(),
new ImageColorOperations());
}
public ImageUtils(IImageDimensionOperations dimension,
IImageColorOperations color) {
this.dimension = dimension;
this.color = color;
}
/* Nothing else needed in this class, ever! */
}
by doing this you get those nice looking calls such as
BufferedImage adjusted = imageUtils.color.adjustHue(3.2f, original);
and when you add some method to either of the interfaces, you already have them available in your image utility class without any additional modification. Yes, generally public fields are a big no-no in Java, however I do think that in this case that's not such a bad thing, especially with the finals marking the fields as unmodifiable (at least in theory).
For short and obvious helper functions, I find that the method itself provides encapsulation enough. And where else would you put them other than a dedicated static class? Yes, many source checkers admonish you for having all-static classes, but if they can't suggest anything better, you should just ignore that. Objects and classes are tools, there is no reason to apply them religiously as the One True Way - there very seldom is one anyway.
Depending on the purpose of those helper functions, you may want to take a look at under each Apache Commons. If those are for example functions which should remove java.lang.* related boilerplate code, then have a look at Commons Lang (Javadocs here). The same exist for java.io.* boilerplate in flavor of Commons IO (Javadocs here) and java.sql.* by DbUtils (Javadocs here).
If those helper functions have really specific purposes and can't reasonably be reused in completely different projects, then I would go ahead with Esko's answer as provided in this topic.
The common practise is to create a class with static methods.
I prefer not to do this, but rather instantiate a class and then call the methods on it. Why ? Because I can then customise that instance in various fashions. To do this with static methods would require you to pass the customisation in with each method call.
My thinking about utility classes is that I don't particularly like them. Whenever I create one, I stop and think carefully as to whether this utility actually belongs in one of the objects I'm modelling, and if it's not a nice fit, perhaps my modelling isn't correct.
I would recommend creating a Util class and dumping any static function that doesn't fit any where else. You should still divide the functions into groups based on what they're used for. Like GUI API, Database API, etc...
The first thing to do, of course, is try to find an (appropriate) place for them to fit within a class structure.
But if there is none, don't shoe-horn, create a third class with helpers. There are two primary strategies for this:
The first strategy employs static methods:
public class FooHelper
{
public static Bar doSomething(Foo) {
}
/* ... */
}
// usage:
Bar b = FooHelper.doSomething(fooInstance);
The other is much the same but in an instantiated class:
public class FooHelper
{
public Bar doSomething(Foo) {
}
/* ... */
}
// usage:
FooHelper fh = new FooHelper();
Bar b = fh.doSomething(fooInstance);
Sometimes you see a Singleton pattern to get an instance but only ever have one instance:
public class FooHelper
{
private static FooHelper theInstance = new FooHelper();
public static FooHelper getInstance() {
return theInstance;
}
public Bar doSomething(Foo) {
}
/* ... */
}
// usage:
FooHelper fh = FooHelper.getInstance();
Bar b = fh.doSomething(fooInstance);
(Note that that's the simplistic Singleton implementation, which of the Singleton implementations is probably appropriate for helpers. It's not appropriate for all Singleton classes.)
There are some substantial advantages to instantiated classes over static functions, not least that helpers can be extended just like any other class. Think of the helper as a thing in its own right, a facilitator. And we model things as classes with instances in the class-based OOP paradigm.
You should take a look at Google Collections and Guava as they have some features which were normally provided as static methods in complete OO style, like
Joining collections/arrays to strings
Splitting strings into collections/arrays
Composition of comparators