views:

194

answers:

8

Here, it says that:

This gives MountainBike all the same fields and methods as Bicycle, yet allows its code to focus exclusively on the features that make it unique. This makes code for your subclasses easy to read. However, you must take care to properly document the state and behavior that each superclass defines, since that code will not appear in the source file of each subclass.

However in my code the inheritance doesn't work properly, probably due to a flaw in my code?

package java1;

class bicycle {
    int speed = 0;
    int gear = 1;

    void accelerate(int incr) {
        speed = speed + incr;
    }

    void decelerate(int incr) {
        speed = speed - incr;
    }

    void changeGear(int val) {
        gear = val;
    }

    void printInfo() {
        System.out.println("Speed: " + speed + " Gear: " + gear);
    }
}

class mountainbike extends bicycle {
    int speed = 10;
}

public class Main {

    public static void main(String[] args) {

        mountainbike mb1 = new mountainbike();

        mb1.accelerate(20);
        mb1.accelerate(10);

        mb1.printInfo();

    }

}

The mountainbike class should inherit all the characteristics of the bicycle class, right? I added a unique property which is int speed = 10, so starting speed should be 10. However on running the compiler treats starting speed as 0.

Any ideas?

+5  A: 

No, your Mountainbike class should not redefine a speed variable. You need to pass the initial speed (10) to the constructor of its super class using super as part of the constructor call:

package java1;

class Bicycle
{

  Bicycle(int speed, int gear)
  {
    this.speed = speed;
    this.gear = gear;
  }

  public void accelerate(int incr)
  {
    speed = speed + incr;
  }

  public void decelerate(int incr)
  {
    speed = speed - incr;
  }

  void changeGear(int val)
  {
    gear = val;
  }

  public String toString()
  {
    return "Speed: " + speed + " Gear: " + gear;
  }

  private int speed = 0;
  private int gear = 1;

}

class Mountainbike extends Bicycle
{
  public Mountainbike()
  {
    super(10, 1);
  }
}

public class Main {

  public static void main(String[] args)
  {    
    Mountainbike mb1 = new Mountainbike();

    mb1.accelerate(20);
    mb1.accelerate(10);

    System.out.println(mb1);
  }
}

I would recommend against using protected variables for speed and gear. It is good practice to enforce encapsulation by declaring the speed and gear variables private in the base class.


EDIT:

Apparently, you're beginning with Java programming. I suggest you have a look at this free online book written by Bruce Eckel: Thinking in Java.

Gregory Pakosz
could the downvoter point the problem so that I can correct it please?
Gregory Pakosz
+1  A: 

In fact you are redeclaring the field speed in your class mountainbike.

for example you can init the speed in the constructor of the class mountainbike.

class mountainbike extends bicycle {
 mountainbike() {
   speed=10;
 }
}
Patrick
+3  A: 

You've introduced a new speed variable in mountainbike which hides the one in bicycle. This is a bad idea - having two variables with the same name at different levels of the type hierarchy will cause confusion, particularly when they're both accessible.

Instead, you want to change the value of the existing variable to 10. For example:

class mountainbike extends bicycle {
    mountainbike() {
        speed = 10;
    }
}

IMO the field should really be private in the base class, accessed via a property instead - and as others have posted, having a constructor in the base class which accepts the initial speed would also be a good idea.

Jon Skeet
+6  A: 
public class Bicycle {
   private int speed;

   public Bicycle (int speed) {
      this.speed = speed;
   }
}


public class Mountainbike extends Bicycle {
   public Mountainbike() {
      super(10);
   }
}
r3zn1k
-1 for missing explanation.
Bombe
@Bombe, seriously...
Gregory Pakosz
What's the 2nd `public Bicycle (int speed) {` (line 4) for?
Fabian
@Fabian it's a constructor
Gregory Pakosz
@Fabian Sun's solution: http://java.sun.com/docs/books/tutorial/java/javaOO/classes.html
r3zn1k
and for the explanation on access modifiers, it's just 2 pages away: http://java.sun.com/docs/books/tutorial/java/javaOO/variables.html
Gregory Pakosz
+4  A: 

You cannot override fields, only methods. What you have to do is mark the speed field as protected, add a constructor to your subclass and set the field's value in that constructor, like this:

class Mountainbike extends Bicycle {
    public Mountainbike()
    {
        speed = 10;
    }
}

BTW, note that I have corrected your class names: Java has an overwhelmingly strong convention for uppercase class names; using lowercase class names will only confuse people who look at your code.

Michael Borgwardt
I would recommend against using `protected` variables. A `private int speed` variable enforces encapsulation better.
Gregory Pakosz
How do you mark it as protected? I get the idea about setting the field (which means variable, right?)'s value in the constructor, but I don't see how you protect the field.
Fabian
@Fabian: you just write `protected int speed;` when declaring the variable. See http://www.codeguru.com/java/tij/tij0020.shtml#Index45
Gregory Pakosz
Just write "protected" in front of the field name (field is a non-local variable). It means that the field is accessible directly by code in subclasses even if they're not in the same package - so it's probably not necessary for your code and will probably be introduced later in your course. but Gregory is right - r3zn1k's solution is cleaner.
Michael Borgwardt
or mine :p anyway, welcome to Java, we hope you enjoy the flight
Gregory Pakosz
+1  A: 

In Java, there's a concept of scopes. What's happening is that the speed variable isn't actually getting overriden, therefore it still defaults to 0.

Mark Basmayor
A: 

You are hiding away bicycle.speed with mountainbike.speed so basically each mountainbike instance has two int member variables for speed, one will be this.speed and the other this.super.speed.

Instead of redeclaring int speed inside mountainbike you should just create a default constructor for mountainbike and set this.speed = xxx; in there.

ruibm
+1  A: 

You can't override a field, only methods.

class bicycle {
    int getSpeed() {
        return 0;
    }
    // ... other things
}

class mountainbike extends bicycle {
    int getSpeed() {
        return 10;
    }
    // ... other things
}
erikkallen