Questions about Java OOP(Inheritence) - java

I am trying to make a videogame that is similar to "Turing Complete". In this game you are supposed to connect circuit pieces to create a computer by the end. So I have a question on inheritance. I have a class called "Circuitware" and every object extends this as follows
public Circuitware implements connectable {
protected int x;
protected int y;
protected int allowedConnetions;
protected Ciruitware[] connections;
private int totalConnections;
public Circuitware(int x, int y, int allowedConnections, Circuitware[] connections) {
this.x = x;
this.y = y;
this.allowedConnections = allowedConnections;
this.connections = new Array[allowedConnections];
for (Object O: connections) {
if (O != null) {
this.totalConnections += 1;
}
}
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public<T> void addConnection(T connection) {
if (this.totalConnections<this.allowedConnections) {
this.connections.add(connection);
}
}
}
Now an example of a subclass is
public class LogicGate extends Circuitware {
String type;
public LogicGate(int x, int y, int allowedConnections, Circuitware[] connections, String type) {
super(x, y, allowedConnections, connections);
this.type = type;
}
public boolean output() {
//Depending on the gate and input we output things
}
}
Now the thing is that the number of allowed connections depends on the type of the circuit, for example logic gates in my game can have 1 connection if it is an NOT gate, 2 connections if it is an AND, XOR, NOR gates or 3 connections if it is and extended OR, extended AND gates, where are switches can only have 0. Is there are better way of doing this?
I also need help understanding that if I have an array of type Circuitware can I add objects from its subclasses? Because the output of logic gates and inputs of other logic gates while they can be inputs to clocks.
Would it be better, design-wise, if I got rid of the "Circuitware" class altogether? But then wouldn't that make connections between different classes harder?

Related

Java - Setting Class Properties Before Super [duplicate]

This question already has answers here:
What's wrong with overridable method calls in constructors?
(8 answers)
Closed 2 years ago.
I have the follow classes:
public abstract class MyAbstractClass {
protected int x;
protected int number;
public MyAbstractClass(int x) {
this.x = x;
this.number = this.generateNumber();
}
public abstract int generateNumber(); // This class is called in the super constructor and elsewhere
}
public class MySubClass extends MyAbstractClass {
private int y;
public MySubClass(int x, int y) {
super(x);
this.y = y;
}
#Override
public int generateNumber() {
return this.x + this.y; // this.y has not been initialized!
}
}
My issue is that MySubClass's y property has to be initialized before the super constructor is run, because a method using y is run in the super constructor.
I am aware that this may not be possible even with some sneaky workaround, but I am yet to find an alternative solution.
Also please keep in mind that I will have many more derived classes, with different values being passed into their constructors.
You can defer the number calculation until it is needed.
public abstract class MyAbstractClass {
protected int x;
protected Integer number;
public MyAbstractClass(int x) {
this.x = x;
}
public int getNumber() {
if (number == null) {
number = generateNumber();
}
return number.intValue();
}
protected abstract int generateNumber();
}

How do you compare multiple properties of objects within an ArrayList using the Comparable Interface? [duplicate]

This question already has answers here:
How to compare objects by multiple fields
(23 answers)
Closed 4 years ago.
I need to sort Rectangle objects in my ArrayList list1 by their corresponding properties: height,width, and topCorner(Point).
I am able to sort the list when evaluating one property.
How can I set up my compareTo method so that it first attempts to sort the objects in the list by height, then by width(if all object heights are equal), and finally bytopCorner(if all object heights and widths are equal)?
public class Point implements Comparable<Point> {
private int x;
private int y;
public Point(){
this(0,0);
}
public Point(int x,int y){
this.x=x;
this.y=y;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int compareTo(Point pt){
if(x==pt.x){
return y-pt.y;
}
else{
return x-pt.x;
}
}
public String toString(){
return "("+x+", "+y+")";
}
}
class Rectangle implements Comparable<Rectangle> {
private int height;
private int width;
private Point topCorner;
public Rectangle(int x,int y,int height,int width){
this.height=height;
this.width=width;
this.topCorner=new Point(x,y);
}
public int getHeight(){
return height;
}
public int getWidth(){
return width;
}
public Point getPoint(){
return topCorner;
}
public int compareTo(Rectangle rect){
if(height!=rect.height){
int compareHeight=((Rectangle)rect).getHeight();
return this.height-compareHeight;
}
else if(width!=rect.width){
int compareWidth=((Rectangle)rect).getWidth();
return this.width-compareWidth;
}
else if(topCorner!=rect.topCorner){
Point comparePoint=((Rectangle)rect).getPoint();
return this.topCorner-topCorner;
}
else{
System.out.println("// ERROR BRO // ERROR BRO //");
}
return 0;
}
public String toString(){
return "(H:"+height+", W:"+width+", P:"+topCorner+")";
}
}
===========================================================================
public class RectangleComparable {
public static void main(String[]args){
Random rn=new Random(21);
ArrayList<Rectangle> list1=new ArrayList<>();
for(int index=0;index<10;index++){
int ran1=rn.nextInt(21), ran2=rn.nextInt(21),
ran3=rn.nextInt(21), ran4=rn.nextInt(21);
list1.add((new Rectangle(5,ran2,ran3,ran4)));
}
System.out.println("KEY : H=height, W=width, P=point\n");
System.out.println("Unsorted List : \n"+list1+"\n");
Collections.sort(list1);
System.out.println("Sorted List : \n"+list1);
}
}
I'll go ahead and apologize if this is somehow a duplicate question. I looked around, but I didn't find anything that gave me a really direct answer (because I'm still a programming noob).
You can write your own Comparator or build one as follows:
Comparator
.comparingInt(Rectangle::getHeight)
.thenComparingInt(Rectangle::getWidth)
.thenComparing(Rectangle::getTopCorner);

Objects override each other

I have the class GameObject:
public class GameObject{
private Coordinate coordinates;
public GameObject(){
coordinates = new Coordinate();
}
public void setCoordinates(int x, int y){
coordinates.x = x;
coordinates.y = y;
}
//More methods here
}
public class Coordinate{
public int x, y;
public Coordinate(){
}
public Coordinate(int x, int y){
this.x = x;
this.y = y;
}
public void setCoordinate(int x, int y){
this.x = x;
this.y = y;
}
And two classes Champion and Spell:
public class Spell extends GameObject{
//Some methods
}
public class Champion extends GameObject{
//Some methods
public Spell fireBall = new Spell();
}
And in my main class:
Champion character = new Champion();
If I call character.setCoordinates(200, 300); (just random numbers), the character goes to these exact coordinates. But the Spell fireBall also goes to (200, 300). So the coordinates in Spell are overriden by the setCoordinates(int x, int y) call to character. How is this possible?
TL;DR - Two classes from GameObject, Spell extends GameObject and Champion extends GameObject, override eachother coordinates. Why?
For full source code:
GameObject.java
Spell.java
Champion.java
Coordinate.java
Looking at your code in gitHub you have 2 methods:
//Set the coordinates for this GameObject
public void setCoordinates(int x, int y){
this.coordinates.x = x;
this.coordinates.y = y;
}
public void setCoordinates(Coordinate coordinates){
this.coordinates = coordinates;
}
If you ever use the 2nd one, then you are sharing the same instance of Coordinates so changing one will change the other
The solution is to copy the values instead
public void setCoordinates(Coordinate coordinates){
this.coordinates.x = coordinates.x;
this.coordinates.y = coordinates.y;
}
In the class Spell you set the coordinates:
this.startCoordinates = startCoordinates;
setCoordinates(this.startCoordinates);
Subsequently this code
if (getCoordinates().x - startCoordinates.x < range) {
is equivalent to
if (getCoordinates().x - getCoordinates().x < range) {
because getCoordinates() references the same object as startCoordinates does.
Your setter method just sets the reference, but it does not copy the object.

How can I use a 'next generation' java data object style together with interfaces?

I'm writing most of my immutable data objects in the following style, which is somtimes described as 'next generation' or 'functional':
public class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
I would like to use the same style for data objects specified by interfaces:
public interface Point {
public final int x;
public final int y;
}
public class MyPoint {
public MyPoint(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Origin {
public Origin() {
this.x = 0;
this.y = 0;
}
}
But this is not allowed by java, which gives an error in the interface code as well as the implementations.
I can change my code to
public interface Point {
public int x();
public int y();
}
public class MyPoint {
private int mx, my;
pulic MyPoint(int x, int y) {
mx = x;
my = y;
}
public int x() {return mx;}
public int y() {return my;}
}
public class Origin {
public int x() {return 0;}
public int y() {return 0;}
}
But it is more code, and I don't think it gives nearly the same feeling of simplicity in the API.
Can you see a path out of my dilemma? Or do you personally use a third, even simpler style?
(I'm not really interested in a discussion of mutable/immutable, getterSetter/new-style or private/public fields.)
I would rather switch to use inheritance or delegation
public class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Inheritance
public class MyPoint extends Point {
public MyPoint (int x, int y) {
super (x, y);
}
....
}
public class Origin extends Point {
public Origin () {
super (0, 0);
}
}

What makes a model change get propagated via JFace databinding?

In order to understand how JFace databindings is working, I have a model object with two properties. Changing one property should set the other to the same value:
public class Model {
private double x;
private double y;
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
public void setX(double x) {
propertyChangeSupport.firePropertyChange("x", this.x, this.x = x);
}
public double getX() {
return x;
}
public void setY(double y) {
propertyChangeSupport.firePropertyChange("y", y, this.y = y);
setX(y);
}
public double y() {
return y;
}
}
Now in a separate class I define two Text widgets, xText and yText, which are bound to this object like this:
DataBindingContext bindingContext = new DataBindingContext();
bindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(xText),
BeanProperties.value(HumidityScanParameters.class,"x").observe(getModel()));
bindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(yText),
BeanProperties.value(HumidityScanParameters.class, "y").observe(getModel()));
I have found that if I change the text in yText, then the setter is automatically called as expected, and this sets both y and x in the model. However, xText is not updated. Why is this? Shouldn't the firePropertyChange() call arrange for the Text to be updated?
Thanks,
Graham.
The compiler was optimising away the initial value of this.x and this.y, which led the PropertyChangeSupport instance to discard the change notification. It didn't think anything had changed. If I introduce a temporary variable like this:
public void setX(double x) {
double oldValue = this.x;
this.x = x;
propertyChangeSupport.firePropertyChange("x", oldValue, x);
}
then the notifications occur as I might expect.
I guess it's because you put this.x to your event before haveing it updated properly.
Try this:
public void setX(double x) {
this.x = x; // update the model!
propertyChangeSupport.firePropertyChange("x", this.x, x);
}
(see comments ;-) )

Categories

Resources