Java: When I Instantiate a Subclass of an Abstract Class It Doesn't Recognize the Constructor of its Superclass - java

I do not have very much Java experience but I see codes where there is an abstract class with a certain constructor and then a subclass of that abstract class without a constructor. Then when the subclass is instantiated it is constructed with its superclass constructor. Is that right?
I have this abstract class:
public abstract class Tile{
public int x;
public int y;
public int z;
protected Color color;
protected float friction;
protected float bounce;
protected boolean liquid;
public void Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
init();
}
abstract protected void init();
And this subclass:
public class TestTile extends Tile{
protected void init(){
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
}
But when I instantiate a TestTile with this:
Tile tile = new TestTile(0, 0, 0);
the init() method never runs. All of the values defined inside it are null. I tried making what I though might be a redundant constructor in the subclass which just called super with the exact same parameters, but when I did that, even with super(x, y, z) the only statement inside it, it said this:
TestTile.java:27: call to super must be first statement in constructor
I want to make a bunch of subclasses of Tile which implement the properties of a Tile. If this is not the correct way to do that, what is a better way?
I am using 32-bit Ubuntu Linux 11.04 if it has to do with anything.
Thanks.

Your constructor is not in propert constructor format, it's void, make it:
public Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
init();
}

I don't see a constructor for TestTime that takes three arguments. I don't see any ctor at all, which means that all you have is the default that the compiler gives you. Did I go too fast and miss it?
I'd recommend paying careful attention to this. I'd rethink this design:
What's wrong with overridable method calls in constructors?
Try this - it includes the fix for your constructor and avoids the issue that the other thread points out:
public abstract class Tile{
public int x;
public int y;
public int z;
protected Color color;
protected float friction;
protected float bounce;
protected boolean liquid;
public Tile(int x, int y, int z){
this.x = x;
this.y = y;
this.z = z;
}
}
public class TestTile extends Tile{
// You're missing this.
public TestTile(int x, int y, int z)
{
super(x, y, z);
this.init();
}
protected void init(){
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
}

First of all, Tile has only one constructor with the x, y, z parameters, no default constructor, so you have to call super(x, y, z) in the TestTile constructor. As slandau said, the "constructor" has a wrong void return type.
The TestTile needs to declare the parameters or pass default values:
public TestTile(int x, int y, int z) {
super(x, y, z);
}
public TestTile() {
super(0, 0, 0);
}
In Java, there are many riscs to call an abstract method in a constructor, see also here, the instance is not initialized properly. You can only call static methods safe (which will not work here).
public TestTile(int x, int y, int z) {
super(x, y, z);
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
or you need to call a private method in the derived class (remove the abstract init() from Tile):
public TestTile(int x, int y, int z) {
super(x, y, z);
init();
}
private void init() {
color = Color.RED;
friction = 0.1f;
bounce = 0.2f;
liquid = false;
}
Are you sure members are the right implementation here? Maybe abstract methods (getters) may be better here to declare a behavior and implement it in the subclass?
public abstract class Tile {
public int x;
public int y;
public int z;
public Tile(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public abstract Color getColor();
public abstract float getFriction();
public abstract float getBounce();
public abstract boolean isLiquid();
}
public class TestTile extends Tile {
public TestTile(int x, int y, int z) {
super(x, y, z);
}
public Color getColor() {
return Color.RED;
}
public float getFriction() {
return 0.1f;
}
public float getBounce() {
return 0.2f;
}
public boolean isLiquid() {
return false;
}
}

Constructors are not inherited, so the three-parameter constructor of Tile is not invoked when you create your TestTile object. You need to explicitly call the three-parameter Tile constructor from a TestTile constructor, like you said you did try, but that call to super(x,x,x) must be the first statement of the TestTile constructor.
And like Matt Ball said, your Tile "constructor" isn't really a constructor until you remove the void return type.

Related

Java - The left-hand side of an assignment must be a variable

I'm trying to make a small program that locates different cities as my first Java project.
I want to access the variables of my class 'GPS' from the class 'City' but I keep getting this error: The left-hand side of an assignment must be a variable. Anyone can explain to me what am I am doing wrong here and how to avoid such mistake in the future?
public class Gps {
private int x;
private int y;
private int z;
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public int getZ() {
return this.z;
}
}
(I want to leave the variables as private)
And this class 'Citiy' should have the coordinates:
class City {
Gps where;
Location(int x, int y, int z) {
where.getX() = x;
where.getY() = y; //The Error Here
where.getZ() = z;
}
}
The error speaks for itself: you cannot assign a value to something that is not a field or a variable. Getters are for getting values stored in the class. Java uses setters to deal with storing the values back:
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
Now you can set values by invoking the setter:
City(int x, int y, int z) {
where.setX(x);
...
}
However, this solution is not ideal, because it makes Gps mutable. You can keep it immutable by adding a constructor:
public Gps(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
Now City can set where in one shot:
City(int x, int y, int z) {
where = new Gps(x, y, z);
}
Don't set properties with getter. It should be done like that:
public class Gps {
private int x;
private int y;
private int z;
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public int getZ() {
return this.z;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setZ(int z) {
this.z = z;
}
}
class City {
Gps where;
City(int x, int y, int z) {
this.where = new Gps();
where.setX(x);
where.setY(y);
where.setZ(z);
}
}

Moving circle towards touched point

i'm trying to move a circle to the point i touch in my running app. I want to see the circle moving along a path towards this point i touch.
I have three classes:
public class Drawing extends View{
Context ctx;
static Circle c1;
private float circleCenterX = 100;
private float circleCenterY = 100;
private float lerpX;
private float lerpY;
private float time = 25;
private float frames = 100;
public Drawing(Context context) {
super(context);
this.ctx = context;
c1 = new Circle (165, 350, 33);
}
public void update(float x, float y) {
this.circleCenterX = x;
this.circleCenterY = y;
}
protected void onDraw (android.graphics.Canvas canvas){
Paint p = new Paint();
p.setColor(Color.GREEN);
lerpX = (circleCenterX - c1.getX()) * (time / frames) + c1.getX();
lerpY = (circleCenterY - c1.getY()) * (time / frames) + c1.getY();
canvas.drawCircle(lerpX, lerpY, c1.getR(), p);
c1.setX(lerpX);
c1.setY(lerpY);
}
public class Circle {
private float x;
private float y;
private float r;
public Circle(float x, float y, float r) {
super();
this.x = x;
this.y = y;
this.r = r;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}`
public class Game extends Activity implements OnTouchListener {
Drawing d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
d=new Drawing(this);
setContentView(d);
d.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent me) {
d.update(me.getX(), me.getY());
d.invalidate();
return true;
}
I think i will need something like a while or for loop to increment the x and y coords and or maybe need a speed value?!
Maybe im totally wrong and its a lot of more math to get it.
Thanks for your help
Cheers
Every time onDraw is called you need to move the circle a bit. The easiest way is just to move a certain number of pixels each time it's called.
To be able to do this you need to keep track of:
Where the animation started
Where you want the animation to end
Use linear interpolation to calculate the position of the circle in each onDraw call

How does inheritance & abstraction work with multiple classes? [java]

I'm having a problem understanding how inheritance works in Java. I have 3 classes that extend each other. The third class is the tricky one which I am having a problem with.
public abstract class Shape{
//methods and variables
protected final static int X_MAX_SIZE = 800;
protected final static int Y_MAX_SIZE = 600;
private int xCord;
private int yCord;
public void setX(int newX){
if(newX > 0 && newX < 800){
this.xCord = newX;
}
else {
System.out.println("Invalid size.");
this.xCord = 0;
}
}
public int getX(){
return xCord;
}
public void setY(int newY){
if(newY > 0 && newY < 600){
this.yCord = newY;
}
else{
System.out.println("Invalid size.");
this.yCord = 0;
}
}
public int getY(){
return yCord;
}
public Shape(){
}
public Shape(int xCord, int yCord){
}
abstract void display();
abstract double area();
}
public class Rectangle extends Shape {
// the inherited methods and calculations
int width, height;
public int getHeight(){
return height;
}
public void setHeight(int newHeight){
this.height = newHeight;
}
public int getWidth(){
return width;
}
public void setWidth(int newWidth){
this.width = newWidth;
}
public Rectangle(){
}
public Rectangle(int x, int y, int height, int width){
setX(x);
setY(y);
setHeight(height);
setWidth(width);
}
#Override
void display(){
String toScreen = "Rectangle X: " + getX() + "\nRectangle Y: " + getY();
String toScreenInfo = "\nRectangle height: " + getHeight() + "\nRectangle Width:getWidth();
String toScreenArea = "\nRectangle area: " + area();
System.out.println(toScreen + toScreenInfo + toScreenArea);
}
#Override
double area(){
return (width * height);
}
}
}
public class Square extends Rectangle {
// more methods, but no new variables. & calculations
public Square(int x, int y, int height, int width){
setX(x);
setY(y);
setHeight(height);
setWidth(width);
}
public Square(){
super();
}
#Override
public void setHeight(int height){
if(height != getWidth()){
height = getWidth();
}
}
#Override
public void setWidth(int width){
if(width != getHeight()){
width = getHeight();
}
}
#Override
double area(){
return (width * height);
}
#Override
void display(){
String toScreen = "Square area is " + area();
}
}
}
the class Square I am having trouble even calling in main.
So my goal here it change the values from Square class to make sure 'height' and 'width' are equal to each other in order to make a square. The constraint being I can't create any new variables in the get/set and constructor.
Inheritance should always express an "is a" relationship between objects, as is true in your example.
A square is a rectangle.
A rectangle is a shape.
If objects do not naturally have an "is a" relationship, then inheritance is probably a bad way to organize them (an interface-based type hierarchy may be better).
A square will have the members (methods and fields) of a rectangle.
A rectangle will have the members (methods and fields) of a shape. A subclass may override a parent method to provide more specific behavior.
If you're having a more particular problem, you'll have to give us more to work with.
if you have any abstract methods in class shape override each and every of it in the Square class or in Rectangle class.
If you would like to create object of Rectangle too then you should override all abstract methods in Rectangle only.
and the inheritance here is multilevel not multiple
What you want can't be done. This is, in fact, the classic example used to demonstrate the Liskov Substitution Principle. Square cannot extend Rectangle, and Rectangle cannot extend Square. To wit:
class Square extends Rectangle {
...
}
public void someMethod(final Rectangle r) {
r.setHeight(300);
r.setWidth(500);
}
final Square square = new Square(200, 200);
someMethod(square);
display(square); // UHOH!!
The problem is that in Rectangle, you have methods setHeight and setWidth, which set the instance variables height and width. In Square, you don't declare new instance variables. So in order to set the height and width, you'll need to use the setHeight and setWidth methods declared in Rectangle.
However, you don't do this for a Square. The Square class overrides the setHeight and setWidth methods. For those to set the instance variables, they will need to call the setHeight and setWidth methods defined in Rectangle. The way to do this is:
super.setHeight(h); // calls the Rectangle method, which sets the variable
super.setWidth(w);
Since you don't use this, the setHeight and setWidth methods in Square just call each other, not the ones in Rectangle, and the result is that the height and width variables never get set.

Inheritance casting

I have two class.
class Vector{
........
Vector(int x, int y, int z){...........}
public Vector sum(Vector vc){
Vector result;
...........//all working and store to Vector result.
return result;
}
public Vector subtract(Vector vc){................//codes}
}
class Velocity extends Vector{
Velocity(int x, int y, int z){......}
................
}
class Test{
public static void main(String args){
Velocity v1=new Velocity(14,14,14);
Velocity v2=new Velocity(14,14,14);
Vector result=v1.sum(v2); //here I want to get this result as Velocity
//I don't know how to get it....
}
}
In similar manner I have Acceleration, Force, Momentum, Displacement class which extends Vector class....And all have same problem......besides this
Vector.java:
public interface Vector<T extends Vector> {
public int getX();
public int getY();
public int getZ();
public T sum(T other);
}
BaseVector.java:
public abstract class BaseVector<T extends Vector> implements Vector<T> {
private final int x;
private final int y;
private final int z;
public BaseVector(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
protected abstract T createNew(int x, int y, int z);
#Override
public T sum(T other) {
return createNew(x + other.getX(), y + other.getY(), other.getZ());
}
#Override
public int getX() {
return x;
}
#Override
public int getY() {
return y;
}
#Override
public int getZ() {
return z;
}
#Override
public String toString() {
return "BaseVector [x=" + x + ", y=" + y + ", z=" + z + "]";
}
}
Velocity.java:
public class Velocity extends BaseVector<Velocity> {
public Velocity(int x, int y, int z) {
super(x, y, z);
}
#Override
protected Velocity createNew(int x, int y, int z) {
return new Velocity(x, y, z);
}
}
Test.java:
public static void main(String[] args) {
Velocity v1 = new Velocity(14, 14, 14);
Velocity v2 = new Velocity(14, 14, 14);
Velocity result = v1.sum(v2);
System.out.println(result);
}
}
Vector result = ((Velocity)v1).sum(v2);
=========================================================
This will not help, because you defined sum in Vector, returning Vector. To make result a Velocity you would need a sum method returning type Velocity, rather than the one in Vector that returns a Vector.
A better alternative might be to provide a Velocity constructor that takes a Vector
Velocity result = new Velocity(v1.sum(v2));

Java how to implement and design an abstract class

I've run into a design problem in my java code. My application uses missiles, and there are different types of missiles that all work identical except they have 3 unique attributes. The constructor of a missile must know these attributes. I decided to make missile an abstract class, but I can't assign values to protected variables in a subclass outside of a method/constructor. Also I can't declare the variables in the constructor, because I must make the call to the super-constructor first thing.
How can I be smart about this problem?
public abstract class Missile {
private int x, y;
private Image image;
boolean visible;
private final int BOARD_WIDTH = 390;
protected final int MISSILE_SPEED;
protected final int MISSILE_HEIGHT;
protected String file;
public Missile(int x, int y) {
ImageIcon ii =
new ImageIcon(this.getClass().getResource(file));
image = ii.getImage();
visible = true;
this.x = x;
this.y = y - Math.floor(MISSILE_HEIGHT/2);
}
public Image getImage() {
return image;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isVisible() {
return visible;
}
public void move() {
x += MISSILE_SPEED;
if (x > BOARD_WIDTH)
visible = false;
}
}
And there is an ideal implementation of a subclass, except it doesn't work. (it can't recognize the protected variables). What do I do?
public class Laser extends Missile {
MISSILE_SPEED = 2;
MISSILE_HEIGHT = 5;
file = "laser.jpg";
public Laser(int x, int y) {
super(x, y);
}
}
I think the best way to do what you want it to do is make abstract methods in Missile that the subclasses have to implement. For example, add these to Missile:
public abstract int getMissileSpeed();
public abstract int getMissileHeight();
public abstract int getFileName();
Then your subclass has to implement it, and you can make it constant like so:
public class Laser extends Missile {
public Laser(int x, int y) {
super(x, y);
}
public int getMissileSpeed() {
return 2;
}
public int getMissileHeight() {
return 5;
}
public String getFileName() {
return "laser.jpg";
}
}
edit: And then of course anywhere that you want to retrieve the constant value you just call those methods.
Change the base class fields and constructors to
protected final int speed;
protected final int height;
public Missile(int x, int y, int speed, int height, String file) {
ImageIcon ii =
new ImageIcon(this.getClass().getResource(file));
image = ii.getImage();
visible = true;
this.speed = speed;
this.height = height;
this.x = x;
this.y = y - Math.floor(height/2);
}
And the subclass to:
public class Laser extends Missile {
public Laser(int x, int y) {
super(x, y, 2, 5, "laser.jpg");
}
...
}
The attributes are already in the base class, so they must not be redefined in the subclass. All-uppercase naming is reserved to constants in Java.
I'm not sure if missile needs to be an abstract class, but I think something like this might be what you're going for:
public abstract class Missile {
private int x, y;
private Image image;
boolean visible;
private final int BOARD_WIDTH = 390;
protected final int MISSILE_SPEED;
protected final int MISSILE_HEIGHT;
public Missile(int x, int y, int speed, int height, String file) {
MISSILE_SPEED = speed;
MISSILE_HEIGHT = height;
ImageIcon ii = new ImageIcon(this.getClass().getResource(file));
image = ii.getImage();
visible = true;
this.x = x;
this.y = y - Math.floor(MISSILE_HEIGHT/2);
}
}
public class Laser extends Missile {
public Laser(int x, int y) {
super(x, y, 2, 5, "laser.jpg");
}
}
Create an interface and put all your final fields in it.
Now implement this interface within Missile and Laser both. At least that would solve the issue of access.

Categories

Resources