Best way to initialize final field in an abstract class - java

I have in mind two ways to initialize a final field in an abstract class and I have to pick the most elegant, correct and understandable for other developers way. There will be at least 10 implementations of my abstract class. Any ideas on which one should I choose?
First way:
public sealed abstract class GuiComponent permits DummyComponent {
private final Node internalNode;
//------Constructor
protected GuiComponent() {
internalNode = Objects.requireNonNull(initInternalNode());
}
//------Protected
protected abstract Node initInternalNode();
protected final Node getInternalNode() {
return internalNode; //subclasses will use this
}
}
public final class DummyComponent extends GuiComponent {
#Override
protected Node initInternalNode() {
HBox hbox = new HBox();
//some Node preparation
return hbox;
}
}
Second way:
public sealed abstract class GuiComponent permits DummyComponent {
private final Node internalNode;
//------Constructor
protected GuiComponent(Node internalNode) {
this.internalNode = Objects.requireNonNull(internalNode);
}
//------Protected
protected final Node getInternalNode() {
return internalNode; //subclasses will use this
}
}
public final class DummyComponent extends GuiComponent {
//------Constructor
public DummyComponent() {
super(initInternalNode());
}
//------Private
private static Node initInternalNode() {
HBox hBox = new HBox();
//...
return hBox;
}
}

In my opinion, the second approach is better. The reason being that the GuiComponent constructor requests a Node, so it is easier to understand that a Node is in fact needed. This makes it explicit, while the other approach makes it implicit because unless you see GuiComponent code, you have no way to know that getInternalNode() method will be called in GuiComponent constructor. You can even say that it is a side-effect of this constructor, as we all know side-effects are usually better avoided in software development.

Related

Changing visibility of method in inherited class

I've got two class: GraphNode and BTNode extends GraphNode. I've got method:
public GraphNode.addChild(GraphNode node)
as GraphNode may have many children
and two methods:
public BTNode.addLeftChild(BTNode left)
public BTNode.addRightChild(BTNode right)
as BTNode may have only two children
How may I restrict public access to inherited addChild(GraphNode node) method from BTNode class? I wouldn't like to have that publicly accessible from that level (while remaining public access from GraphNode class)?
If you extend (or implement) from a class (or interface) then the parent will specify the whole signature of a method. There is nothing you can change about it, you will always need to have the method public if your parent specifies it as public.
Otherwise you would run into problems when casting like ((Parent) child).theMethod(). The object itself is child but the view gets reduced to the Parent class. The method gets invoked from the child class, so it would be private although you casted it to Parent which specified it as public.
However you could do something like:
public class Child extends Parent {
#Override
public void theMethod() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
private void otherMethod {
// Do something
}
}
But note that saying "I am extending class XY but not supporting all of its methods" is not the best design. It is a sign that the parent class (or other parts of the architecture) could have been structured more modular in the first place.
It is not possible to reduce the visibility of a method in subclass. The subclass need to be a valid instance of the base class.
As you can see in the previous answers, it is not possible to change visibility of public methods in the child classes. But in case of you are designer of GraphNode class, you could use a little bit another class hierarchy:
public abstract class BaseNode {
protected final Map<String, GraphNode> children = new HashMap<>();
protected void addChild(String id, GraphNode node) {
children.put(id, node);
}
}
public class GraphNode extends BaseNode {
public void addChild(GraphNode node) {
children.put(String.valueOf(System.currentTimeMillis()), node);
}
}
public class BTNode extends BaseNode {
private static final String LEFT = "left";
private static final String RIGHT = "right";
public void addLeftChild(BTNode node) {
addChild(LEFT, node);
}
public void addRightChild(BTNode node) {
addChild(RIGHT, node);
}
}

Extending an abstract class with an abstract builder vs concrete class and concrete builder

I would like to use the builder pattern in some upcoming work that I have which has several classes in a hierarchy. The base class will have at least 9 fields to start, and the various sub-classes may add between 2-4 more fields each. This would get out of hand very quickly and the builder pattern is appealing to me for this exact reason. I got some initial exposure to the builder pattern in books and articles. They were helpful, but had nothing on how to extend this pattern. I tried to implement this by myself, but I ran into trouble with the constructors of each of the sub-classes because I didn't get how to pass the collected data in the builder to super class. I looked on SO for some answers, and here's what I found.
This one is from SO 24243240 where an example of how to extend an abstract class with an abstract builder is given. It is also based on this blog post.
public abstract class AbstractA {
protected String s;
protected int i;
protected AbstractA() {
}
protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
protected T object;
protected B thisObject;
protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
protected ABuilder() {
object = getObject();
thisObject = thisObject();
}
public B withS(String s) {
object.s = s;
return thisObject;
}
public B withI(int i) {
object.i = i;
return thisObject;
}
public T build() {
return object;
}
}
}
public final class ConcreteA extends AbstractA {
private String foo;
protected ConcreteA() {
}
public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
#Override protected ConcreteA getObject() {
return new ConcreteA();
}
#Override protected Builder thisObject() {
return this;
}
public Builder() {
}
public Builder withFoo(String foo) {
object.foo = foo;
return this;
}
}
}
And then in client code, it would look like...
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();
I like this example because it allows you to easily extend these classes, but it also seems to me that this defeats the purpose of using the builder pattern because the methods withS(String s) and withI(int i) act alot like setter methods. Also, this method leaves the fields of the base class and the builder class as protected rather than private.
Here's one from SO 17164375
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
I like that this one seemingly adheres more closely to the builder pattern described by Josh Bloch and it also allows you to simply pass the builder into the constructor for the class you want to instantiate. This would be a nice way to do some validation inside the builder before instantiating the object in the call to build(). At the same time though, this example shows how you can extend the builder pattern with concrete classes, and when you do that the potential for all the nastiness that comes with extending concrete classes (e.g. inconsistent interfaces, inheriting methods which can corrupt the state of your object, etc.)
So my question is there a way to implement an abstract class with an abstract builder that also allows you to pass in a reference to a builder in the constructor for the base class? Something like:
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
I realize that you can't instantiate an object the way that I've shown here, but is there some other way to do it I mean? Is this possibly where a factory would go? Maybe I just have the wrong assumptions about the builder pattern in general. :) If that's the case, is there a better direction to take?
Your first example is not bad, but I don't think it is what you are looking for.
I am still a little unsure of exactly what you want, but seeing your examples do not work for you, I thought I'd give you one or two of my own. :)
class ParentBuilder{
public ConcreteParent build(){
ConcreteParent parent = new ConcreteParent();
parent.setFirst(1);
parent.setSecond(2);
parent.setThird(3);
return parent;
}
}
class ChildBuilder{
public ConcreteChild build(ParentBuilder parentBuilder){
ConcreteParent parent = parentBuilder.build();
ConcreteChild child = new ConcreteChild();
child.setFirst(parent.getFirst());
child.setSecond(parent.getSecond());
child.setThird(parent.getThird());
child.setFourth(4); //Child specific value
child.setFifth(5); //Child specific value
return child;
}
}
Any new type, would have its own builder, taking in its parent's builder.
As you can see this is similar to:
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
In your example.
This however, quickly gets out of hand as well, increasingly for the number of variables and subclasses.
An alternativ, would be to use dynanic variables, have a look at this: http://martinfowler.com/apsupp/properties.pdf
Martin Fowler writes a great article specifying all the pros and cons.
Anyways, here's my second example:
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}
The magic here is, you (might) no longer need all these subclasses.
If these subclasses' behavior does not change, but only their variables, you should be fine using a system like this.
I strongly advise that you read Martin Fowler article on the subject though, there are good places and bad places to do this, but I think this is a good one.
I hope this brings you closer to an answer, good luck. :)

Enforcing instantiation of object in subclass

I got a very easy question here, but don't know in what direction to search...
I built a class that extends another class with an uninstantiated object. How do I make sure I dont forget to instantiate the object in the subclass? Here's what I mean:
public class Hitbox{
....
}
public class Enemy{
protected Hitbox hbox; // edit: changed to protected
}
public class AngryLady extends Enemy{
hbox = new Hitbox(10, 20); // Must not forget this!
}
One way would be to always check if (hbox!=null) before using thishandle, but that feels silly. There has to be an easier way like with abstract classes, where already the compiler gives an error when a method from the abstract class has not been implemented.
Just initialize your variable in the constructor of the parent class:
public abstract class Enemy{
protected Hitbox hbox;
public Enemy(int a, int b) {
hbox = new Hitbox(a, b);
}
}
public class AngryLady extends Enemy {
public AngryLady(int a, int b) {
super(a, b);
}
}
If you need a different HitBox instance per subclass of Enemy, use Factory method pattern. This is a very simple example:
public enum HitboxType {
ANGRY
}
public final class HitboxFactory {
private HitboxFactory() {
}
public static Hitbox createHitbox(HitboxType hitboxType) {
switch(hitboxType) {
case HitboxType.ANGRY:
return new AngryHitbox();
case <another_case>:
return <respective hitbox>
}
//in case of invalid parameter
return null;
}
}
And it would be better using dependency injection:
public abstract class Enemy{
protected Hitbox hbox;
public Enemy(Hitbox hitbox) {
hbox = hitbox;
}
}
public class AngryLady extends Enemy {
public AngryLady(Hitbox hitbox)) {
super(hitbox);
}
}
//...
AngryLady angryLady = new AngryLady(HitboxFactory.createHitbox(HitboxType.ANGRY));
//...
Another tip in case you don't want to have null Hitboxes is to create an empty Hitbox:
public class EmptyHitbox extends Hitbox {
public EmptyHitbox() {
super(0,0); //or whatever arguments it needs
}
}
And in the factory method:
public static Hitbox createHitbox(HitboxType hitboxType) {
switch(hitboxType) {
/* ... */
}
//in case of invalid parameter
return new EmptyHitbox();
}
First it should be protected since subclass doesn't have access to private fields.
public class Enemy{
protected Hitbox hbox;
}
To make sure you don't forget, you should really initiate the object where you are declaring it - the parent class.
public class Enemy{
//if you just don't want/need to define a constructor explicitly and you know a b ahead.
int a = 0;
int b = 0;
protected Hitbox hbox = new Hitbox(a, b);
}
In this case, you can always use hbox in the subclass without worrying about it.
Since the hbox field is inherited from the parent class, it should be initialized at the parent class:
public class Enemy {
private final static int DEFAULT_H = 10;
private final static int DEFAULT_W = 10;
// default initialization
private HitBox hbox = new HitBox(DEFAULT_W,DEFAULT_H);
public HitBox getHBox() {
return hbox;
}
}
Unless hbox must be initialized differently for each subclass, in which case you should use chained constructors to initialize the HitBox.
public class Enemy {
private final HitBox hbox;
public Enemy(HitBox hbox) {
this.hbox= hbox;
}
public HitBox getHBox() {
return this.hbox;
}
}
public class AngryLady extends Enemy{
public AngryLady() {
super(new HitBox(10, 20));
}
}
This example assume Enemy is not an abstract class.

How to make extendible ArrayList?

At the moment I'm working on a game and things are going pretty good. What keeps me busy at the moment, is making a mob spawner which spawns mobs in a certain area.
The big problem is right now, I'm not really sure how to keep track of all the mobs being spawned by the spawner, as there are different inheritances of mobs.
This is my MobSpawner class:
public class MobSpawner {
protected List<Mob> mobs;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxMobs = 0;
public MobSpawner(Level level) {
this.level = level;
}
}
And this is my RoachSpawner class:
public class RoachSpawner extends MobSpawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>(); // Roach is an extension of Mob
}
}
This is not gonna work because the List and ArrayList must be of the same type.
So the question is, does anyone have any other ideas how to do this?
Thanks in advance!
I'm presuming that Roach extends Mob.
You can use an ArrayList<Mob> to hold Roaches. So:
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
And if you just use ArrayList<Mob> in all the implementations, you can allocate it in the base instead (assuming ArrayList is always the container you want -- if you want to use other List types see kwah's answer and have subclasses create list):
public class MobSpawner {
protected final List<Mob> mobs = new ArrayList<Mob>();
...
}
And just have the subclasses use the base's list.
Instantiating the list in the base class and making it final has a bonus side-effect of letting you state the following invariants (presuming you don't violate them with reflection or anything):
A MobSpawner will never have a null mobs, and
mobs will reference the same object throughout the entire lifetime of a MobSpawner.
Being able to make those assumptions can possibly simplify some of your logic in other places.
Making it final also enforces, at compile time, that you're not inadvertently replacing it with another list somewhere.
If you are not already doing so, try taking advantage of supertypes.
In the same way that you can declare a variable to be a List and then instantiate it to be an ArrayList, try saying your List contains Character items and then fill it with specific implementations of the Characters (eg List<Character> is instantiated as ArrayList<Mob> and ArrayList<Roach>).
public abstract class Character { }
public class Mob extends Character { }
public class Roach extends Character { }
public class Spawner {
protected List<? extends Character> characters;
protected Level level;
protected int timer = 0;
protected int spawnTime = 0;
protected int maxCharacters = 0;
public Spawner(Level level) {
this.level = level;
}
}
public class RoachSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Roach>();
}
}
public class MobSpawner extends Spawner {
public RoachSpawner(Level level) {
super(level);
mobs = new ArrayList<Mob>();
}
}

Extending an object with Builder Pattern using an inner class

What I'm trying to do is create a class (Square) that uses a Builder pattern, and then extend this class as an inner class (MyCube) inside the Object where it's needed (DrawMyCube).
For reasons that are a bit to complex to get into it's preferred to extend these as inner classes (references to local variables).
I've tried to make the example as simple as possible because the real use case is too complex to use on here:
public abstract class Square {
protected Integer length;
protected Integer width;
public abstract static class Builder {
protected Integer length;
protected Integer width;
public abstract Builder length(Integer length);
public abstract Builder width(Integer width);
}
protected Square(Builder builder) {
this.length = builder.length;
this.width = builder.width;
}
}
Now I need to extend and use this in here:
public class DrawMyCube {
private String myText;
private Integer height;
private String canvas;
private MyCube myCube;
public DrawMyCube(String canvas) {
this.canvas = canvas;
myCube = new MyCube.Builder().length(10).width(10).text("HolaWorld").build();
}
public void drawRoutine() {
myCube.drawMe(canvas);
}
protected class MyCube extends Square {
protected String text;
public static class Builder extends Square.Builder{
protected String text;
public Square.Builder length(Integer length) {this.length = length; return this;}
public Square.Builder width(Integer width) {this.width = width; return this;}
public Square.Builder text(String text) {this.text = text; return this;}
}
protected MyCube(Builder builder) {
super(builder);
this.text = text;
}
protected void drawMe(String canvas) {
canvas.equals(this);
}
}
}
However the problem is the static Builder in the inner class:
The member type Builder cannot be declared static; static types can
only be declared in static or top level types.
Alternatively, I can create the inner class MyCube as a regular class, but then the problem becomes that I can not refer back to anything inside the DrawMyCube class (and in the real use case there are many references to various of these).
Static nested classes can only be declared in a static context, which is why you're seeing that compiler error. Just declare your Builder class adjacent to MyCube (or anywhere else in static context, it doesn't matter). For example:
public class DrawMyCube {
protected class MyCube extends Square { }
public static class MyCubeBuilder extends Square.Builder { }
}
Note that the builder will need a reference to the outer DrawMyCube instance in order to instantiate a new MyCube. For this reason you might just make it an inner (non-static) class of MyCube:
public class DrawMyCube {
protected class MyCube extends Square { }
public class MyCubeBuilder extends Square.Builder { }
}
As you can see I still declared it adjacent to MyCube because having a builder as an inner class to what it builds just doesn't make sense.
Edit: As you mentioned, a simple alternative would be to make MyCube static:
public class DrawMyCube {
protected static class MyCube extends Square {
public static class Builder extends Square.Builder { }
}
}
Because honestly there isn't a huge benefit to using inner classes - just the implicit outer instance reference - and this would let you keep your existing hierarchy and naming conventions. You can easily implement the reference to the outer DrawMyCube yourself - it just takes a little more code.
As a side note you're probably going to want to use generics to implement your builder pattern, for example an abstract Builder<T> where an implementation builds an instance of T. As it is, there won't be a way to narrow down what your deriving builder classes produce. Here's a sketch of what I'm hinting at:
abstract class Square { }
abstract class SquareBuilder<T extends Square> { }
class MyCube extends Square { }
class MyCubeBuilder extends SquareBuilder<MyCube> { }

Categories