setting superclass fields in subclass - java

I have an abstract Java class that has a hashcode field that should be initialized by the concrete subclasses. I was thinking of making the initialization method abstract, i.e.,
abstract class A {
protected int hashcode;
// hashcode should be initialized in constructor
protected A () { hashcode = setHashcode(); }
abstract int setHashcode() {} // implemented by subclasses
}
But unfortunately different subclasses need to take in different number of arguments for setHashcode, e.g., class B might compute hashcode using two of its fields and class C might need three, but since the call to super has to be the first line in B's constructor this scheme won't work. So I am wondering if there is a different way / design pattern to solve this problem?

but since the call to super has to be the first line in B's constructor this scheme won't work
Why wouldn't it work? If you put calculations of the hash code in a static function of a subclass, you would be able to pass pre-made hash code to the constructor of your superclass.
class BaseClass {
private int hashCode;
protected BaseClass(int hashCode) {this.hashCode = hashCode;}
}
class DerivedClass : BaseClass {
private static int calcHash(String str) {
return str.hashCode();
}
public DerivedClass(String s) {
super(calcHash(str));
}
}

You don't really need to store the value in the superclass, just declare an abstract getHashCode that subclasses will override.
public abstract class Base {
protected abstract int getHashCode();
}
This is better because the "intent" of the method is preserved, regardless of its storage requirements.
Incidentally, hashCode is already defined in Object, and can be overridden by subclasses. If your concept of hash code is different than what Object provides, maybe you should rename it.

It sounds like an interface might be appropriate for the initialization so any subclasses you create can just overload the interface implementation.

Change:
abstract int setHashcode();
To:
abstract int getHashcode(Object...objects);
And the subclass needs to inspect the count and type of objects passed.
Then you make calls like:
hashcode = getHashcode();
hashcode = getHashcode(o1);
hashcode = getHashcode(o1,o2);

Related

Cannot pass super keyword as an argument to method in java

Why below program does not work fine?
instead of super in below code if we give this keyword as an argument it will work fine, what is the difference between two codes.
Thanks in advance
class Vehicle
{
int maxSpeed = 120;
}
/* subclass Car extending vehicle */
class Car extends Vehicle
{
int maxSpeed = 180;
void display()
{
test(super);
/* print maxSpeed of base class (vehicle) */
// System.out.println("Maximum Speed: " + super.maxSpeed);
}
public void test(Vehicle obj)
{
System.out.println("Maximum Speed: " + obj.maxSpeed);
}
}
/* Driver program to test */
class Test
{
public static void main(String[] args)
{
Car small = new Car();
small.display();
}
}
There is a misconception on your end. this refences to a real object, therefore you can pass it to any method that allows for an instance of the corresponding class.
But there is no separate super object! super is nothing but a helper mechanism that allows you to access methods or fields of the super class (and it only works within a derived class). It is not intended to deliver a real object refence!
And note: that also doesn't make sense conceptually. You can't really separate the super class properties when looking at a child class due to polymorphism.
It is really simple: you pass this, nothing else. If your code doesn't work then, then that would be a symptom of a bug in your design!
Welcome to StackOverflow.
Your method test receives a instance of a Car, and keyword super it's used to call parent methods, through child class. this keyword returns the instance of the class.
What you're trying to achieve is call super() constructor to pass a instance of a Car to the method, but java states that the the super() call can be used only once in the constructor class as the first statement, to ensure that class will inherit from it's parent, or Object class directly. If you not states it, Java implicitly does it for you.

toString() behavior of object when not overridden

If the toString() method of a class is not overridden (or overloaded), and another method that returns a string is defined in the class, then what happens when I pass an instance of the class where a String is expected?
If your class extends Object, you will get the result of Object#toString(), which is what will be called. If your class extends something else, it will get the first #toString in the inheritance path.
Fun fact: It takes less time to test this than asking a question on Stack Overflow and getting an answer.
As you may know, every single class you create directly or indirectly inherits from the almighty Object class! If you don't override toString, calling toString will result in a call to the toString method of the nearest ancestor.
Suppose A inherits from B which inherits from C which inherits from D. Only C has overridden toString.
Calling toString on an object of... will result in calling the toString of...
A C
B C
C C
D Object
I hope you understand that.
Actually, not only does the toString behave like this. Every method does this as well!
Now that you know Object.toString will be called. What does it do actually?
From this answer, we know that Object.toString outputs something like this:
FullyQualifiedNameOfYourClass#12345
FullyQualifiedNameOfYourClass basically means your class name, followed by the package that it is in e.g. com.example.MyClass.
12345 is the hashcode of the object, returned by hashCode() on the object.
So will Object.toString call one of your class' methods that returns a string, if you ever declared one?
Nope. Because it just doesn't. The documentation of toString clearly says that it just returns something like FullyQualifiedNameOfYourClass#12345 and nothing else.
Even if it did, it makes no sense. What if you declared two methods that return a string? Which one should it choose? Also, reflection takes time and will slow down the whole thing.
Using the name of the class where a String is expected is not allowed. Consider the following:
class Foo {}
class Bar {
public void baz(String a) {
// Do something
}
public void binky() {
baz(Foo); // Compiler error
}
}
However, you could do the following:
class Foo {}
class Bar {
public void baz(String a) {
}
public void binky() {
Foo b = new Foo();
baz(b.toString());
}
}
Because the .toString() method of class Foo is not overridden, you will inherit the default .toString() from the Object class. This default behavior will print a string consisting of the name of the class of which the object is an instance, the at-sign character #', and the unsigned hexadecimal representation of the hash code of the object. (Thanks Kevin!)

Java: What member value returned on unimplemented abstract method?

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.

Is this Overloading, methods with same name in different classes and different signature?

If I have the following code in Java:
class A {
public int add(int a , int b) {
return (a+b);
}
}
class B extends A {
public float add(float a , float b) {
return (a+b);
}
In this particular case the sub-class isn't exactly overriding the base class's add function as they have different signatures and the concept of overloading occurs only if they are in the same scope. So, is the function add(float , float) in the sub-class B treated as an entirely new function and the concept of overloading and overriding is not applicable to it? And does it use 'Static binding' or 'Dynamic Binding'?
Method add in class b is an overload of add in class a. Not an override. An override would just be a different implementation of the original add method.
In brief, yes. To override, you need to replicate the complete method signature, which includes the method name, parameters and return types. From the tutorial
An instance method in a subclass with the same signature (name, plus
the number and the type of its parameters) and return type as an
instance method in the superclass overrides the superclass's method.
You might want to consider the #Override annotation, which will trigger a compiler error if you don't successfully overrride a method.
In this particular instance, it perhaps looks like you don't need overriding so much as some solution including generics. So you could instantiate a class a<Integer> and a similar class a<Float>
In that case you are not overriding the method, since the signatures are different.
But there is overloading in class b, since you have two methods with the same name but different parameters (one if class a, and the other one in class b)
Hope it helps.
There can be a method that is not overridden but overloaded in the subclass. Here the subclass has two add() methods. The version which accepts int arguments(not overridden), and the overloaded method add() which accepts float arguments.
I think in this particular case neither overloading nor overriding occurs, because return type must be same in case overloading and overriding, so neither static binding nor dynamic binding happens in this case.
method overloading is not possible in case of different return type, because compiler can't figure that which method he need to call.
I know it's late answer but i think it's important question need to be answered for beginners.
One key point in overloading is it works in inheritance.
Next is either it's Static binding or Dynamic binding.
It is Static Binding So, why?
Static Binding
Static binding in Java occurs during Compile time.
private, final and static methods and variables uses static binding and bonded by compiler.
Static binding uses Type (class in Java) information for binding.
Dynamic Binding
Dynamic binding occurs during Runtime.
Dynamic methods bonded during runtime based upon runtime object.
Dynamic binding uses Object to resolve binding.
But the important part is here
Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime.
Java compiler determines correct version of the overloaded method to be executed at compile time based upon the type of argument used to call the method and parameters of the overloaded methods of both these classes receive the values of arguments used in call and executes the overloaded method.
B a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
So if you will create reference of type B then it will search for proper argument type
and for above code it will execute both methods.
A a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
but for above code it will give compile time error for float arguments.
Hope it clears all doubts.
First things first
Is it method overriding ?
No , since to override a method you need to replicate the complete method signature as pointed out in Brian Agnew's answer and as I explain below.
Is it overloading ?
Yes , Method "add" has an overloaded implementation in Class B.
Consider the following code:
class C{
public static void main(String args[]){
B a = new B();
a.add(2 , 3);
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.print("INT ");
return a + b;
}
}
class B extends A {
public double add(double a , double b) {
System.out.print("Double ");
return a + b;
}
}
OUTPUT : INT Double
So , the method in Class B in your code overloads the add method that it inherits from its parent
Does it use Static Binding or Dynamic Binding ?
This is what makes me conclude that OP is confused.It is static binding because it is a overloaded function. The only way to think of dynamic binding would have been in below scenario
class C{
public static void main(String args[]){
A a = new B();
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.println("A : INT");
return a + b;
}
}
class B extends A {
public int add(int a , int b) {
System.out.println("B : INT");
return a + b;
}
public double add(double a , double b) {
System.out.println("Double");
return a + b;
}
}
Output : B : INT
Here , the parent class A has a contract that says , "I have an add behaviour for ints" . class B inherits this add behaviour and makes it more specific and at the same time also provides a new behaviour where it can add doubles.
But class A has "no knowledge of this behaviour".
So an object of class A "cannot" add doubles. To do that you need a more specific type of A object i.e. a B object.
The method add() in class A is also available to class B by inheritance, therefore the method is overloaded in class by changing the data type from int, int to float, float.
The concept of Overloading comes in play if and only if the functions are in the same scope or class.
cz if this is the case of method overloading then for same method signature or same argument type the compiler gets confuse and must give compile time error .
but in the above program in class B if you pass the same argument in same order then according to overloading it must give error but it is not happening u can check it i already have.
It is the case of inheritance where through object reference if you call any method then the compiler will check it in child class ,if its not there then it will look into parent class that the above program is all about.
hope this is helpfull.

Java - Abstract class into normal class

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.

Categories

Resources