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> { }
Related
I have parent class Hammer and then his child class Mjolnir. I want to set the remainingUsage for Mjolnir to 4. I managed to do it by creating method in Hammer classs called setUsage and then use it in Mjolnir constructor. Is it possible to do it in more easy way without that setUsage method?
public class Hammer extends AbstractActor {
private int remainingUsage;
private Animation image;
public Hammer() {
this.remainingUsage = 1;
image = new Animation("sprites/hammer.png");
setAnimation(image);
}
}
public class Mjolnir extends Hammer {
Mjolnir(){
super();
this.setUsage(4);
}
}
You can do something like this:
...
private remainingUsages;
public Hammer() { this(1); }
public Hammer(int remainingUsages) { this.remainingUsages = remainingUsages; }
And then just call super(4) from your subclass. Calling other methods within your constructor is not good practice.
Please find the below snippet :
class Rule
public class Rules {
public static final JarvisFilterRule FILTER = new JarvisFilterRule();
private static class JarvisFilterRule extends RelOptRule {
private JarvisFilterRule() {
super(operand(Filter.class, operand(Query.class, none())));
}
public void onMatch(RelOptRuleCall call) {
// do something
}
}
}
class RelOptRule
public abstract class RelOptRule {
/**
* Description of rule, must be unique within planner. Default is the name
* of the class sans package name, but derived classes are encouraged to
* override.
*/
protected final String description;
public abstract void onMatch(RelOptRuleCall call);
}
My question is : How can I access the onMatch() method of nested class Rules.JarvisFilterRule?
The purpose of the private key word is to prevent access to class members that need to be used exclusively by the class declaring it.
In your case, the Rules class defines JarvisFilterRule to be a private inner class with the intention that its implementation should be known only to the Rules class.
If you wish to access the JarvisFilterRule::onMatch() method inside another class, you will need to replace the private modifier of JarvisFilterRule with public or move the inner class JarvisFilterRule to its own separate file and make it a public class. Like this:
JarvisFilterRule .java
public class JarvisFilterRule extends RelOptRule {
public JarvisFilterRule() {
super(operand(Filter.class, operand(Query.class, none())));
}
public void onMatch(RelOptRuleCall call) {
// do something
}
}
-- OR --
public class Rules {
public static final JarvisFilterRule FILTER = new JarvisFilterRule();
public static class JarvisFilterRule extends RelOptRule {
private JarvisFilterRule() {
super(operand(Filter.class, operand(Query.class, none())));
}
public void onMatch(RelOptRuleCall call) {
// do something
}
}
}
Hope this helps!
Rules.FILTER.onMatch(...)
JarvisFilterRule is not an inner class. An inner class in Java is a nested class that is not static.
I've been trying my best with some basic code, and I am completely stuck...
I have an abstract class "Piece":
public abstract class Piece {
private static int type;
public int getType() {
return type;
}
}
The "Pawn" is the Child:
public class Pawn extends Piece {
private static final int type = 1;
}
And now for the problem: When creating the Pawn with Pawn p = new Pawn();, p.getType() returns 0, not 1...
How can I fix this?
The problem is that you already have a variable declared in your abstract class. You shouldn't redeclare it in your subclass. Instead, set the abstract class's variable like this:
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
You should also declare the variable as protected so that subclasses can access it and refrain from making it static, since that will allow only one value for all subclasses:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
This code you write relies on an instance and not on a static context:
Pawn p = new Pawn();
p.getType();
A static final field is not designed to be inherited by child classes.
And creating a static final field in the child class with the same name as in the parent class doesn't allow to override it either.
1) So you should use an instance field and not a static field for the type field.
2) If you want to override the behavior of getType() in the child class, in fact you don't even need to use a field. Using a method should be enough.
In the base class :
public abstract class Piece {
public int getType() {
return 0;
}
}
In the child class :
public class Pawn extends Piece {
#Override
public int getType() {
return 1;
}
}
Here is one way. But you really need to read up on classes and abstract classes.
public abstract class Piece {
public int getType() {
return 0;
}
}
public class Pawn extends Piece {
public int getType() {
return 1;
}
}
Having a static variable in a class means that all instances of that class share the same value. I don't think that's what you intended.
Also, you can use the hierarchy of inheritance to your advantage by not redefining the getType() method.
Here is one of many ways to solve it:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
There are two problems with your approach.
The first is that Java does not support inheritance of static methods. Not that it couldn't have supported this - it's just a design choice. What this means is that any method of class Piece, which calls getType() - calls the Piece class' implementation of getType(), not a polymorphic call to getType() of whatever the actual subclass is.
The second problem is that you're sort of reinventing the wheel. Java has rich reflection facilities: You can use getClass() and instanceof for your check:
if(myObject instanceof Piece && myObject.getClass() != Piece.class) {
// do stuff
}
and of course you can make this a method of the piece class (no need to override it).
I'm currently in a Java-based university class and for coding samples the professor is using protected fields for the subclasses to access.
I asked if this was bad practice and was told it is normal. Is this true, why not use setters and getters for abstract methods? I thought it was always best practice to restrict as much information as possible unless required otherwise.
I tested out using setters and getters with abstract parent and it works fine for abstract parent classes that are subclassed. Although abstract classes cannot be instantiated, they can still be used to create objects when a subclass is instantiated as far as I understand.
Here is a short example:
public abstract class Animal {
protected int height;
}
public class Dog extends Animal {
public Dog() {
height = 6;
}
}
public class Cat extends Animal {
public Cat() {
height = 2;
}
}
As opposed to using:
public abstract class Animal {
private int height;
public getHeight() {
return height;
}
public setHeight(int height) {
this.height = height;
}
}
public class Dog extends Animal {
public Dog() {
setHeight(6);
}
}
public class Cat extends Animal {
public Cat() {
setHeight(2);
}
}
While you can certainly do both ways the protected field way is less desirable and I would argue less idiomatic particularly if this is library code that you plan to share.
You can see this in the Java Collections API as well as Guava. You will be hard pressed to find Abstract classes that have protected fields (let alone any fields).
That being said there are always exceptions and you are not always writing library code (ie public api).
Here is my opinion on protected and/or private fields and abstract classes. If you are going to do it than make a constructor that takes the initial values:
public abstract class Animal {
private int height;
public Animal(int height) { this.height = height; }
public int getHeight() { return this.height }
}
public class Cat extends Animal {
public Cat() {
super(2);
}
}
Now your subclasses are required to set height to something as they have to call the constructor that takes height.
In your first example, only subclasses of Animal can access the protected field height.
In you second example, any class whatsoever can manipulate the field height indirectly via the public setter method.
See the difference?
I try to implement a fluent interface in my 2D game engine.
Simplified example of my implementation:
public class Sprite<T> {
protected float x = 0.0;
protected float y = 0.0;
public T setPosition(float x, float y) {
this.x = x;
this.y = y;
return (T)this;
}
}
public class Living<T extends Living> extends Sprite<Living> {
protected boolean alive = false;
public T setAlive(boolean alive) {
this.alive = alive;
return (T)this;
}
}
public class Entity<T extends Entity> extends Living<Entity> {
protected String name = null;
public T setName(String name) {
this.name = name;
return (T)this;
}
}
Entity entity = new Entity().setPosition(100, 200).setAlive(true).setName("Zombie");
I keep getting the error: "The function setAlive(boolean) does not exist."
I know, using my methods the other way round (in a more logical order) works:
Entity entity = new Entity().setName("Zombie").setAlive(true).setPosition(100, 200);
And I know that overwriting any parent setter functions in each and every child class would work:
public class Entity extends Living {
protected String name = null;
public Entity setPosition(float x, float y) {
return (Entity)super.setPosition(x, y);
}
public Entity setAlive(boolean alive) {
return (Entity)super.setAlive(alive);
}
public Entity setName(String name) {
return (Entity)super.setName(name);
}
}
But I want the interface to be as free/uncomplicated as possible for the 'end user' and the code to be as compact and clean as it gets.
I don't know if I just messed up the generics or my hole approach is completely wrong. I hope you can help. I am open to any advice. (Sorry for my bad english.)
Edit:
I already tested the following approach and it works for the Entity class.
public class Sprite<T> {
...
}
public class Living<T> extends Sprite<T> {
...
}
public class Entity extends Living<Entity> {
...
}
I forgot to mention, that I need to instantiate Sprite & Living too. For example:
Living living = new Living().setPosition(50, 50).setAlive(false);
This is a valiant attempt at the curiously recurring template pattern in Java. The problem is that you're mixing generics and raw types which means you aren't "closing the loop" of the pattern. For example your declaration of Living:
public class Living<T extends Living> extends Sprite<Living>
Should really be:
public class Living<T extends Living<T>> extends Sprite<T>
At some point you'll need to declare a "leaf" class that resolves T, otherwise you won't be able to instantiate and declare variables of these types without resorting to raw types or wildcards (which defeats the purpose of the pattern). For example:
public final class ConcreteEntity extends Entity<ConcreteEntity>
See my answer here for more details on implementing this pattern.
I think your class model is over complicated, you can pass generic parameter down to the child class and then declare it explicitly:
public class Sprite<T> {
...
}
public class Living<T> extends Sprite<T> {
...
}
public class Entity extends Living<Entity> {
...
}