I have an abstract class which lays out what each of its subclasses should implement. Most methods will have different implementations for each subclass, but some will be the same for all. I want the methods that will be the same to be to be defined in the abstract class, so that I'm not pasting the same method into several different classes. However, when I call that method on an instance of the abstract's subclass, I receive a nullpointer because, I imagine, the method implemented in the abstract class is referencing the abstract's field, not the instance's field.
Can someone point out where the flaw is?
For example:
abstract class ControlView {
String[] controls;
abstract void render();
void release() {
for (int i = 0; i <= controls.length; i++) {
//Release the controls
}
}
}
class StartingControls extends ControlView{
String[] controls;
Button uiDrawButton;
Button uiLoadButton;
StartingControls() {
this.controls = new String[2];
uiDrawButton = new Button();
this.controls[0] = uiDrawButton;
uiLoadButton = new Button();
this.controls[1] = uiLoadButton;
}
public void render() {
//Unique Render implementation
}
}
When I call
instanceOfStartingControls.release();
I obviously want to iterate over the two strings that I put into instanceOfStartingControls' controls field when it was constructed. I do not want to iterate over the non-initialized array that is apparently living in the abstract.
Is it some combination of access modifiers or static methods that is keeping this from working as it seems it should, or am I missing some crucial bit of knowledge on abstract classes? This feels like a basic question, but I'm having a hard time putting it to words, so I've not been satisfied with any results from my searches.
There are two arrays called controls. The one in the derived class is obscuring the one in the base class, thus the base instance never gets set non-null.
Delete the declaration from the derived class.
This issue is not related to the base being abstract. If you use the same field name in a derived class as is used in a base class, the base instance will be obscured.
Related
I'm somewhat confused in understanding how polymorphism actually works. At most, I understand that a superclass reference variable can refer to a subclass object reference, but I can't use that reference variable to access any of the subclasses fields and methods. Take for example this sample program:
public class Game
{
public static void main(String[] args)
{
Human hero = new Knight();
hero.stats();
}
}
class Human
{
public void stats()
{
System.out.println("HP: 10 STR: 25.");
}
}
class Knight extends Human
{
public void skill()
{
System.out.println("Sword master");
}
public void weapon()
{
System.out.println("Sword");
}
}
From the sample program above, the only method I can call using the reference variable, hero, is the one declared within the class Human, but I have no access to any methods declared in the Knight class.
If I were to include the following whoAmI() method in both the Human and Knight class, the reference variable then refers to the subclass overriden method:
{...
hero.whoAmI() // calls the method declared in the Knight class
}
class Human
{
public void whoAmI()
{
System.out.println("Just a regular human");
}
}
class Knight extends Human
{
public void whoAmI()
{
System.out.println("A mighty knight");
}
}
While I do understand why the overriden method whoAmI() is called instead of the superclass' method, since the JVM (correct me if I'm wrong) sees that the reference variable contains a reference to a knight object, why can't I access any of the methods declared within the Knight class using the reference variable?
Human hero = new Knight();
You defined your hero to be a class Human. Therefore, you will only inherit those properties that are available to its parent class.
If you define your hero as a Knight, then you will have access to both Human and Knight properties.
Knight hero = new Knight();
a few nitpicking: better declare your properties private, and use a getter/setter.
Hope this helps.
Because, it breaks the contract.
Let's assume (just to understand the why) that Java allows you to call a Knignt class method on a Human class reference and you publish a public method like
public void doHumanThings(Human being) {
...
// but somewhere inside the method you call
being.doKnightThings();
...
}
This breaks the contract because other classes can't simply pass a Human object like
Human onlyHuman = new Human();
someObj.doHumanThings(onlyHuman);
That's because if they do, your code breaks at runtime when calling
onlyHuman.doKnightThings(); // ERROR!
because All Humans cannot be Knights.
So, although you've declared to the rest of the Java world classes (with a public method in a public class) that you expect a Human object, you're breaking the contract by expecting it to behave like a Knight which the other client classes may not be even aware of.
You can't simply assume that a Human reference will always point to a Knight object. The only way you can enforce that is by declaring the reference of type Knight itself.
However, if a method implementation wants to mostly make use of the parent class behaviour but add or adapt in case a subclass object is received, then an explicit downcast following an instanceof check can be performed as
public void doHumanThings(Human being) {
being.doHumanThings();
...
// Is this Human a Knight too?
if (being instanceof Knight) {
Knight iAmAKnightToo = (Knight) being;
// OK. Using a Knight reference now.
iAmAKnightToo.doKnightThings();
}
}
Think it this way
Knight hero = new Human();
Why this is wrong ?
Since accessible/visible methods depend on the type of reference variable hero.
So all child methods can be called logically but technically u are not holding the object of child class so u cannot call the child methods.
Similarly u are holding a base class reference
Human hero = new Knight();
The methods that are visible/accessible depends on the type of reference variable in which you are holding the object and not on the object.
So if you change it to
Knight hero = new Knight();
All the methods become accessible (base class and child class).
why can't I access any of the methods declared within the Knight class
using the reference variable
Because at compile time, compiler only knows about the reference used, so only methods available in the reference type class are available.
Poplymorphism is also called dynamic binding because it is decided at the run time depending on the object, which class method will be called.
You can only access the methods from the type of the left side of the declaration. Java sees the object 'hero' as a Human not a knight. This helps with type safety in iterators and the like (more advanced than this question I think). This is a safety feature that ensures certain methods are implemented but can also be overridden or not.
So only the methods in the left hand declaration are available. It may seem annoying now but in more advanced polymorphic problems this is a very nice type safety.
Every class and every interface defines a contract. Contract is defined by public methods (very simplified).
Contract means what methods you can call on the object extending a class or implementing an interface. If you store an object (Car) to a reference of different type (Vehicle):
Vehicle v = new Car();
You are basically saying treat the car as a vehicle. Once you say that you are using the contract of the Vehicle and not the car.
That means you can only call methods defined in the Vehicle and not the new ones in Car.
Human hero = new Knight();
Human = Referance Type , hero= Reference variable ,
new Knight() = Object Type
if you call a overriden method ; Object Type decides which method can be called.
if you call a non-overriden method ; Reference type decide which method can be called.
In Java, if I have a class such as this
abstract class TestClass
{
int mMember = 0;
int getMember()
{
return mMember;
}
}
and a class that extends this class:
class TestExtended extends TestClass
{
int mMember = 1;
}
If I create an instance of TestExtended, and call testExtended.getMember(); would it return 0, or 1?
In other words, when I extend a class, and don't override a method from said class, does it call the method and act on the members in said class, or in the extended class?
Would I need to re-implement (copy-paste) the function in the extended class to get the function to return 1?
It will return 0, not 1.
This is because you cannot "override" fields from a superclass. You can set them, so long as they are not private, but if you declare a new variable with the same name, it will simply shadow the superclass variable.
On the other hand, you can override methods.
Now, shadowing member variables in this way is usually a Very Bad Idea™, and is another reason to avoid public fields. This is why:
TestExtended sub = new TestExtended();
sub.mMember = 5;
System.out.println(sub.mMember); // prints '5', as expected
TestClass sup = sub; // this is fine, TestExtended extends TestClass
System.out.println(sup.mMember); // prints '0'!
The compiler will choose which version of the variable to use based on the compile-time type, breaking polymorphism. Don't shadow member variables, and avoid public fields, and this will never matter. Use getters and setters instead.
It can be confirmed by running. It will return 0. This is because the fields cannot be overridden. What you are actually doing is hiding the instance variable as per jls.
overriding of methods differs from hiding of fields (§8.3), for it is
permissible for a field to hide a field of another type.
Check Example 8.4.8.3-4. in language specification for more info
To get the subclass version, you would have to:
class TestExtended extends TestClass
{
int mMember = 1;
#Override
int getMember(){
return mMember;
}
}
Base class methods cannot access subclass fields (at least, without using reflection). Full stop.
Also, fields do not participate in overriding, unlike methods.
Using testExtended.getMember(); obviously means you are calling the abstract class method because you dont override the method in your sub-class. if you would have overridden it then the preference would have been given to subclass method first if your object is of type subclass. so in this case it will give you 0 unless you override the method.
I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.
I am having some confusion about extended classes. I think the best way to explain what I want to do is with some skeleton code:
abstract class Player
{
public int solve()
{ // One method of solving problem
}
}
class otherPlayer extends Player
{
public char solve(int num)
{ //Different method of solving same problem
}
}
// I suspect this is a wrong way to create Player
Player first = new otherPlayer;
// Because this gives me an error...
first.solve(5)'
// And this uses the super class's method of solving problem
first.solve();
// I don't want to do this though...
otherPlayer first = new otherPlayer;
// Because I actually define the Players in a method
// that returns a type Player():
private Player genPlayer()
{ // Take input from keyboard
Player newPlayer;
if (specific set of answers)
newPlayer = new otherPlayer();
else newPlayer = new Player();
return newPlayer;
}
My understanding of extended classes is limited. If I say "TypeA var = new TypeB", and TypeB extends TypeA, it seems that var only has access to methods in the TypeA class. What does it do, then to say it is a new TypeB? Why is that even a legal way to instantiate a variable? And how would you recommend I restructure this program so I can make it work (I'd prefer to keep the method, so I don't have to make a mess every time I create a Player)?
I really just want to know how to create an extended class as if I were a person who knew what he was doing.
You need to do something like:
abstract class Player {
abstract void solve(int num);
}
class OtherPlayer extends Player {
void solve(int num) {
//...
}
}
That is, to call a method through variables of type Player, at least its signature must be declared on that class - and must be implemented in all subclasses. There is no way to call a method that may or may not exist in a subclass using a variable of the superclass type.
Imagine you could do this:
class Player {
// ...
}
class FooPlayer extends Player {
void solveInt(int num) {
// ...
}
}
class BarPlayer extend Player {
void solveString(String s) {
// ...
}
}
Player[] players = new[] {new FooPlayer(), new BarPlayer()};
// this is the sort of code you want to work
for (Player p : players) {
p.solveInt(123);
}
what's supposed to happen when the method is called on BarPlayer? As you can see, it doesn't make much sense to allow this.
While it's not very useful to do Player player = new FooPlayer() explicitly, it does let you not have to know which exact subtype of Player the value is. It's missing the point to look at the methods that are different between the subtypes - the point of polymorphism is that the same method (i.e. with the same signature) is implemented in a different way between the subclasses:
class Player {
abstract String greet();
}
class EnglishPlayer extends Player {
String greet() {
return "Hello";
}
}
class JapanesePlayer extends Player {
String greet() {
return "Konnichi wa";
}
}
The point of TypeA a = new TypeB() is programming to contract. It means you can change TypeB into any other type that extends TypeA and be guaranteed not to have to change any other line of your code.
first, you are getting an error in the instantiation syntax. It should be new otherPlayer(). Also classes should be capitalized in java.
I assume the code is within a method, otherwise it will not compile.
Finally, to answer your question why you extend a class, if otherPlayer had its own implementation solve() (no arguments) then which method would be called would depend on the instantiation you used, not on the variable type. In other words, first.solve() would call the method in otherPlayer, not in player.
extension is about superclasses and subclasses.
if typeA is a subclass of typeB, then you could say
typeA extends typeB, and typeA would inherit all of the methods of typeB
it only works one way, kind of like a child can inherit traits from their parents, but the parents don't inherit anything from the child
if you want a method in the subclass to behave differently than in the parent class, simply write a new method with the same name/parameters. subclass methods automatically override superclass methods. then, if you want to use the superclass version of a method, you can use the super keyword
Inheritance is something that happens when you extend a class, you need to figure out the common methods you want in your class and subclass and define any alternates in your subclass.
Check this out for more info: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
you declared 'first' as a Player reference that is referencing an otherPlayer object. This is legal, but if you want otherPlayer behavior, you will have to typecat 'first':
((otherPlayer)first).solve(5)
First of all, you can't instantiate abstract classes, so you can't code newPlayer = new Player();.
Then, it's perfectly legal to write something like ClassA a = new ClassB(); as long as ClassB is a subclass of ClassA and ClassB is not an abstract class.
In the case you have a method in ClassB that overrides a method of ClassA, which one is called depends on the dynamic type of the object that is actually the type you used for instantiate that object, this is called Polymorphism. There is lot of material about this (Object Oriented Programming and Java) on the web, but I think a great place to start at, is the book Thinking in Java by Bruce Eckel, he offers the third edition for free at his site (http://www.mindview.net/Books/TIJ/).
public abstract class Figure
{
private int offset;
public Figure()
{
offset = 0;
}
public Figure(int theOffset)
{
offset = theOffset;
}
public void setOffset(int newOffset)
{
offset = newOffset;
}
public int getOffset()
{
return offset;
}
public abstract void drawHere();
/**
* Draws the figure at lineNumber lines down from the
* current line.
*/
public void drawAt(int lineNumber)
{
int count;
for(count = 0; count < lineNumber; count++)
System.out.println();
drawHere();
}
}
In this class, it handles the figure for creating a tree. I am trying to turn it into a normal class by simply giving a body to the abstract method. I noticed that when I remove the abstract tags, it still works perfectly normal. But my question is, if I want to make the class non-abstract, through what means would I go through to do this?
This class is extended upon by 2 other classes and then it has the main class. Do I have to go through and modify those too?
You shouldn't be altering Figure; you should be extending it.
This class is extended upon by 2 other
classes and then it has the main
class. Do I have to go through and
modify those too?
All the more reason to not alter Figure: you'll break the rest of the code.
You should not be modifying anything. Create a new class that extends Figure and override the abstract drawHere() method with the behavior you want.
When you have an abstract class,
abstract class AbstractCar {
float maxSpeed;
Driver whoIsDriving;
AbstractCar(float ms, Driver d) {
maxSpeed = ms;
if(!validateDriver(d)) throw new InvalidDriverException();
whoIsDriving = d;
}
abstract boolean validateDriver(Driver d);
}
You can define the behavior separately for various conditions by extending and defining the abstract methods in question.
class CrappyCar extends AbstractCar {
boolean validateDriver(Driver d) {
return d.hasLicense() && d.hasInsurance();
}
}
class ExpensiveCar extends AbstractCar {
boolean validateDriver(Driver d) {
return d.hasLicense() && d.hasInsurance() && d.hasGoodJobInCaseHeMessesUpMyCar();
}
}
If you want a non-abstract class, then you must not declare it with the abstract modifier (i.e. just public class Figure). There shouldn't be any need to modify any derived classes (so long as they themselves are not abstract).
Technically speaking, in order to make an abstract class non-abstract you have to:
Provide implementation for all abstract methods
Since you now have a valid implementation of everything define, remove all abstract tags
There is no need to modify anything in inheriting classes (assuming they are non-abstract theirselves) because they already provide an implementation of all the abstract methods of their parent & are free to override any method they wish.
Whether or not you should make your class non-abstract is another point of discussion.
You are correct that removing the abstract keywords and implementing the abstract methods makes the class non-abstract.
However, you normally do not want to turn the class itself from abstract to non-abstract. A class is not abstract until you add this keyword, so you (or someone else) apparently had a reason to make sure it's not a normal class, but an abstract one.
If you think about it at a very high level (far from Java), then a "Tree" is something you know how to draw. Similarly, you could imagine a subclass "Circle" for which you know what a drawing shoud look like. For the very generic "Figure", however, you have no idea what it means to draw it.
This is the idea of why the actual drawing is left abstract in your Figure class. Hence, you should not make Figure non-abstract, but instead focus on the classes that extend from it and make those non-abstract, by implementing all abstract methods from Figure. In your Tree class, you know what drawHere should do, so implement it there to print a tree. In another class, like Circle you implement it differently, but it never really makes sense to implement it in Figure, where you have no idea what to draw.
You can declare a method body for drawHere() (presumably empty, since, as #Frank pointed out, you can't really have any idea about how to draw a Figure) and remove the abstract modifiers. Then you will have a concrete class. That means someone could create a new Figure(). This won't be either of the two subclasses you now have, just a Figure.
If such an object (that does nothing when it is called upon to drawHere()) would not be useful (and, in particular, if you would consider it an error to have such an object), then you should keep the class abstract. This reasoning applies even when you can define an implementation for every method.
If a class is made abstract you can give body to all the methodes or none of these but if any class is extending abstract class it must implement all the methode which is only being declared.