I am new to Java and I am learning the basics. I was studying the toString method and how to override it in my own classes. I am just wondering why has toString to be public? is it because it is defined so in the Object class?
From official Oracle documentation:
Modifiers
The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.
This because inheritance creates an IS-A relation between two classes, for which the Liskov substitution principle must be valid. Without having the previous constraint that would be impossible to enforce.
Think about it: You subclass Gizmo with MyGizmo. This means that any place that a Gizmo can be used, you can use a MyGizmo in it's place. If some program does gizmoObject.toString() then that should work even if gizmoObject is not a Gizmo but a MyGizmo.
In particular, toString is used for printing & dumping objects and needs to be accessible on all objects.
When you override any method, the visibility of the override must be at least as visible as the base method.
When you override any method, the visibility of the override must be equal or more than the visibility of the base method
When overriding a method, you should declare the visibility of overridden method as the the one in the base class or wider.
Here is a note about the overriding rules I wrote it myself as a reference to me:
/* Access Modifiers */
1- Access modifier in child should be same or greater (the sequence:
public - protected - default (package-private) - private). Access
modifier in parent should not be private. If a child don't have access
to the parent's method, then overriding the method without the
#Override annotation will consider it as a new method.
/* Return Types */
2- Return type in child should be the same class or sub-class.
/* Exceptions */
3- If the parent's method throws checked exception, then the child's
method can: a- throw the same exception or sub-class. b- not to
throw any exceptions. c- throw runtime exceptions.
4- If the parent's method throws unchecked exception, then the child's
method can: a- not to throw any exceptions. b- throw runtime
exceptions.
5- If the parnet's method does not throw exception, then the child's
method can: a- not to throw any exceptions. b- throw runtime
exceptions.
Because you are overriding a method, you must define it as the prototype method or more than that.
when you override an sub class method visibility must be wider than parent class.
Wider to strict order:
public
default
protected
private
Related
I understand why java doesn't allow to set weaker access privileges for overridden methods, but why is it the same for static methods? I mean, these methods only hide each others, right? So what's the problem from the encapsulation point of view?
P.S.
I know that there are 5 rules for hiding a method
The method in the child class must have the same signature as the method in the parent
class.
The method in the child class must be at least as accessible or more accessible than the
method in the parent class.
The method in the child class may not throw a checked exception that is new or
broader than the class of any exception thrown in the parent class method.
If the method returns a value, it must be the same or a subclass of the method in the
parent class, known as co-variant return types.
The method defined in the child class must be marked as static if it is marked as
static in the parent class (method hiding). Likewise, the method must not be marked
as static in the child class if it is not marked as static in the parent class (method
overriding).
But after all, I don't get the idea from the encapsulation prospective
The same rules are valid and for method hiding
https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3
Static methods have special access permissions that allow friend access to members within a instance. For example, you could have a static method called create that creates a default instance of the class and directly modifies data within the instance without using instance properties or instance methods (just for a usage example, not necessarily a usage recommendation).
Because of this special access, lower access permissions to the static methods could allow you to create an object in a state that you could not otherwise use, or modify an object in an unpredictable and non-encapsulated way.
This is only a minor annoyance for most user-defined classes, but allowing this when sub-classing e.g. containers could expose serious undefined behavior problems.
The Java compiler doesn't complain when I override a protected method with a public method. What's really happening here? Is it overriding or hiding the parent method since the parent method has lower visibility?
A sub-class can always widen the access modifier, because it is still a valid substitution for the super-class. From the Java specification about Requirements in Overriding and Hiding:
The access modifier (ยง6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.
If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.
From the point of view of an external class, the public method is just a new method, not an overriding method, since the external class could not access the protected method anyway.
On the other hand, lowering the visibility is not allowed because the external class can always use a reference of the type of a super-class to reference an object of the sub-class and call the same method.
The visibility only affects external accessibility. Being a public method any external class can call it.
Access level of the overriding method doesn't affect visibility of the original method. After override, with any access levels, the original method can only be accessed by calling super in the subclass.
let's say we have this method
public class Animal {
public void eat() { }
}
and on another class that extends Animal has this method
public String eat(){}
is this considered as method overriding? because I've heard that you can use different return types in method overriding providing they have the same method arguments
This is neither overloading , nor overriding ! It is compilation error .
In Java it is possible to define two or more methods within the same class that share the same name, as long as their parameter declarations are different. When this is the case, the methods are said to be overloaded, and the process is referred to as method overloading.
Following are rules of method overriding in java which must be followed while overriding any method. private, static and final method can not be overridden.
1)Method signature must be same including return type, number of method parameters, type of parameters and order of parameters.
2)Overriding method can not throw higher Exception than original or overridden method. This rule only applies to checked Exception in Java, overridden method is free to throw any unchecked Exception.
3)Overriding method can not reduce accessibility of overridden method , means if original or overridden method is public than overriding method can not make it protected.
You can only change the return type to a subclass of the original return type.
All answers are correct from a technical point of view because Void is a class in Java that no other class can extend and when methods are overridden the return-type has to be a sub-type of the original type (parentReturnType.isAsignableFrom(overriddenReturnType)).
But from a practical point of view the question is still valid and it would have made sense to make an excuse for the special case void. The only value a variable of the type Void can hold is null. Further no variable can have the primitive type void. Finally you can not compile this code:
Void result = object.notify();
So in the end it would have made sense to specify Java differently when 1.5 was introduced and allow overriding void return types with any other type.
Therefore the only reasonable answer is IMHO it is not possible because Java was designed such that this is not allowed.
This not correct Code, as two methods with same name should return same value, only arguments can be differents
Overriding is having same method with same arguments in the subclass
Overloading having same method name with different argumens
The return type of a method is not part of that method's signature.
When you call eat() on the subclass, java looks at the signature you provided (eat with no parameters) and starts looking for a method with this signature, starting in the class of the instance type of the object you call it on (and searches through its ancestors if it fails to find it).
So, methods called on a subclass will always run the overridden methods (they're found first).
A critical 'point' of OO (specifically polymorphism) is that a subclass can be passed in where the superclass was expected.
If a method wants to call the superclass' eat() method and get a void, but you passed a subclass into that method of which eat() returned a String; you can see that method will call the subclass' eat and get an unexpected value.
You can see why this could be a problem. :I
So, overriding methods must return the same type or a subclass of the type returned by the parent.
(Similar principles apply as to why you can return a subclass; I'll let you think about it c: )
It's neither overriding nor overloading, it creates compilation error.
Two methods with same name, different param numbers or different type of params known as overload method, return type may be same or different. It may be in same class or parent, child classes.
Two methods having same param numbers, same types, same return types but one is in parent class and other is in child class are known as overrided methods.
This is a very naiveish question, but here goes:
An overriden method from a base class will mean that calls to the sub class will call the derived, overriden method, correct?
Thus, if there is no override annotation, the method in the base class will be called. So the override method will serve purely to document the intent - call one version of a method over the other.
Is this the case?
This leads me to the following question:
What is the difference between an abstract class which 5-6 classes may derive from but the methods inherited in the derived classes are not overriden, and one class (Static or not being irrelevant), used by those 5-6 classes?
The #Override annotation is intended ONLY to catch errors at compilation time. It does not affect override behavior at runtime. The idea is that you give the compiler the chance to inform you that your method name or signature is wrong.
The override annotation is simply a marker to show the the method overrides a superclass method.
It being there has no effect at runtime. See here:
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Override.html
Using abstract is an architectural design to ensure that users either must implement an abstract method (declared but not implemented in the base class) or that they all have access to the same base methods and data (this is the same as the latter example you gave).
Thus, if there is no override
annotation, the method in the base
class will be called.
No. The overriding method in the derived class will always be called.
So the override
method will serve purely to document
the intent - call one version of a
method over the other.
Is this the case?
No. As per the other answers, it tells the compiler to insist that there was something to override.
Please refer to the Java code below:
class Base{
Base(){
System.out.println("Base Constructor");
method();
}
void method(){}
}
class Derived extends Base{
int var = 2;
Derived(){
System.out.println("Derived Constructor");
}
#Override
void method(){
System.out.println("var = "+var);
}
}
class Test2{
public static void main(String[] args) {
Derived b = new Derived();
}
}
The output seen is:
Base Constructor
var = 0
Derived Constructor
I think var = 0 occurs because Derived object is half initialized; similar to what Jon Skeet says here
My questions are:
Why does the overridden method get called if the Derived class object isn't created yet?
At what point in time is var assigned value 0?
Are there any use cases where such behavior is desired?
The Derived object has been created - it's just that the constructor hasn't been run yet. The type of an object never changes in Java after the instant it is created, which happens before all constructors run.
var is assigned the default value of 0 as part of the process of creating an object, before constructors are run. Basically, the type reference gets set and the rest of the memory representing the object gets wiped to zero (conceptually, anyway - it may already have been wiped to zero before, as part of garbage collection)
This behaviour at least leads to consistency, but it can be a pain. In terms of consistency, suppose you had a read-only subclass of a mutable base class. The base class may have an isMutable() property which was effectively defaulted to true - but the subclass overrode it to always return false. It would be odd for the object to be mutable before the subclass constructor ran, but immutable afterwards. On the other hand, it's definitely strange in situations where you end up running code in a class before the constructor for that class has run :(
A few guidelines:
Try not to do much work in a constructor. One way of avoiding this is to do work in a static method, and then make the final part of the static method a constructor call which simply sets fields. Of course, this means you won't get the benefits of polymorphism while you're doing the work - but doing so in a constructor call would be dangerous anyway.
Try very hard to avoid calls to non-final methods during a constructor - it's very likely to cause confusion. Document any method calls you really have to make very clearly, so that anyone overriding them knows that they will be called before initialization has finished.
If you have to call a method during construction, it's usually not then appropriate to call it afterwards. If that's the case, document it and attempt to indicate it in the name.
Try not to overuse inheritance in the first place - this is only going to become an issue when you've got a subclass deriving from a superclass other than Object :) Designing for inheritance is tricky.
Why does the overridden method get
called if the Derived class object
isn't created yet?
Derived class constructor implicitly calls the Base class constructor as the first statement. Base class constructor calls method() which invokes the overridden implemention in the Derived class because that is the class whose object is being created. method() in Derived class sees var as 0 at that point.
At what point in time is var assigned
value 0?
var is assigned the default value for int type i.e. 0 before the contructor of Derived class is invoked. It gets assigned the value of 2 after the implicit superclass contructor call has finished and before the statements in Derived class's constructor start executing.
Are there any use cases where such
behavior is desired?
It is generally a bad idea to use non-final non-private methods in the constructors/initializers of a non-final class. The reasons are evident in your code. If the object that is being created is a subclass instance, the methods may give unexpected results.
Note that this is different from C++, where the type does change while the object is being constructed, so that calling a virtual method from the base class constructors doesn't call the derived class's override. The same thing happens in reverse during destruction. So this can be a small trap for C++ programmers coming to Java.
There are some properties of the Java language specification that should be noted in order to explain this behavior:
A superclass' constructor is always implicitely/explicitely called before a subclass' constructor.
A method call from a constructor is just like any other method call; if the method is a non-final, then the call is a virtual call, meaning that the method implementation to invoke is the one associated with the runtime type of the object.
Prior to a constructor execution, all data members are automatically initialized with default values (0 for numeric primitives, null for objects, false for boolean).
The sequence of events is as follows:
An instance of the subclass is created
All data members are initialized with default values
The constructor being invoked immediately delegates control to the relevant superclass' constructor.
The super constructor initializes some/all of its own data members, and then calls a virtual method.
The method is overriden by the subclass, so the subclass implementation is invoked.
The method tries to use the subclass' data members, assuming they are already initialized, but this is not the case - the call stack hasn't returned to the subclass' constructor yet.
In short, whenever a constructor of a superclass invokes a non-final method, we have the potential risk of entering into this trap, therefore doing it is not recommended.
Note that there is no elegant solution if you insist on this pattern. Here are 2 complex and creative ones, both requiring thread synchronization(!):
http://www.javaspecialists.eu/archive/Issue086.html
http://www.javaspecialists.eu/archive/Issue086b.html