Hiding methods in subclass - java

I have a abstract superclass with some implemented methods.
Is it possible to hide methods from this superclass in an subclass inheriting from this superclass? I don't want to have some methods visible from the superclass in some of the subclasses. Last but not least, is it possible to change the number of arguments for a method in the subclass which has the same name in the superclass?
Let's say we have a method public void test(int a, int b) in the superclass but now I want a method public void test(int a) in the subclass which calls the superclass function and the method from the superclass not visible anymore.

Is it possible to hide methods from this superclass in an subclass inheriting from this superclass?
If you make the method private in the super class, it won't be visible in the subclass (or to any one else).
If you need the method in the base class to be public however, there is no way of hiding it in the subclass by for instance overriding it with a private implementation. (You can't "reduce visibility", i.e. go from for instance public or protected to private in a subclass.)
The best workaround is probably to override the method and throw for a runtime exception such as UnsupportedOperationException.
is it possible to change the number of arguments for a method in the subclass which has the same name in the superclass?
No, you can't change the signature. You can create another method with the same name and a different number of arguments but this would be a different (overloaded) method and the method in the base class would still be visible.

You can't completely hide a method from superclass, it's always possible to call, e.g.
MyBase o = new MyClass();
o.test(1, 2);
However, you can override the method in a specific way:
class MySuper {
public void test(int a, int b) {; }
}
class MyClass extends MySuper {
#Deprecated
#Override
public void test(int a, int b) {
throw new UnsupportedOperationException("Do not call this method, call test(int a) instead!");
}
public void test(int a) { ; }
}

No you cannot hide a public method in a child, for instance by making the method private there.
The reason is that having an instance of the child class, you may always cast it to the base class, and call the method there.
So this behaviour is logical. Either redesign the class hierarchy or create a new class if this is becoming a too ugly API.
You may however override the method and
/**
* Use <code>test(a)</code> instead.
* #param a.
* #param b.
*/
#Deprecated
#Override
public void test(int a, int b) {
throw new UnsupportedOperationException("Use test(int) instead.");
}
public void test(int a) { // Overloaded method
int b = ...;
super.test(a, b);
}
Overloading a method is possible: same name, different parameter types.

Java doesn't support reducing visibility.
There is a way to do something like this but it's complex:
You need to create an interface for the parent type. This interface doesn't need to have methods.
You create another, new type Delegate which implements the method public void test(int a, int b)
You delete the current parent type.
You create two new types which implement the interface. One delegates the call test(a,b) to Delegate and the other one creates a new method test(a) which eventually uses a Delegate instance.
So the type which implements the old code is never visible to the outside world (it could be a package private class).

Related

Java: Is there a way to use a method defined in a superclass, along with added functionality in the subclass? [duplicate]

I'm currently learning about class inheritance in my Java course and I don't understand when to use the super() call?
Edit:
I found this example of code where super.variable is used:
class A
{
int k = 10;
}
class Test extends A
{
public void m() {
System.out.println(super.k);
}
}
So I understand that here, you must use super to access the k variable in the super-class. However, in any other case, what does super(); do? On its own?
Calling exactly super() is always redundant. It's explicitly doing what would be implicitly done otherwise. That's because if you omit a call to the super constructor, the no-argument super constructor will be invoked automatically anyway. Not to say that it's bad style; some people like being explicit.
However, where it becomes useful is when the super constructor takes arguments that you want to pass in from the subclass.
public class Animal {
private final String noise;
protected Animal(String noise) {
this.noise = noise;
}
public void makeNoise() {
System.out.println(noise);
}
}
public class Pig extends Animal {
public Pig() {
super("Oink");
}
}
super is used to call the constructor, methods and properties of parent class.
You may also use the super keyword in the sub class when you want to invoke a method from the parent class when you have overridden it in the subclass.
Example:
public class CellPhone {
public void print() {
System.out.println("I'm a cellphone");
}
}
public class TouchPhone extends CellPhone {
#Override
public void print() {
super.print();
System.out.println("I'm a touch screen cellphone");
}
public static void main (strings[] args) {
TouchPhone p = new TouchPhone();
p.print();
}
}
Here, the line super.print() invokes the print() method of the superclass CellPhone. The output will be:
I'm a cellphone
I'm a touch screen cellphone
You would use it as the first line of a subclass constructor to call the constructor of its parent class.
For example:
public class TheSuper{
public TheSuper(){
eatCake();
}
}
public class TheSub extends TheSuper{
public TheSub(){
super();
eatMoreCake();
}
}
Constructing an instance of TheSub would call both eatCake() and eatMoreCake()
When you want the super class constructor to be called - to initialize the fields within it. Take a look at this article for an understanding of when to use it:
http://download.oracle.com/javase/tutorial/java/IandI/super.html
You could use it to call a superclass's method (such as when you are overriding such a method, super.foo() etc) -- this would allow you to keep that functionality and add on to it with whatever else you have in the overriden method.
Super will call your parent method. See: http://leepoint.net/notes-java/oop/constructors/constructor-super.html
You call super() to specifically run a constructor of your superclass. Given that a class can have multiple constructors, you can either call a specific constructor using super() or super(param,param) oder you can let Java handle that and call the standard constructor. Remember that classes that follow a class hierarchy follow the "is-a" relationship.
The first line of your subclass' constructor must be a call to super() to ensure that the constructor of the superclass is called.
I just tried it, commenting super(); does the same thing without commenting it as #Mark Peters said
package javaapplication6;
/**
*
* #author sborusu
*/
public class Super_Test {
Super_Test(){
System.out.println("This is super class, no object is created");
}
}
class Super_sub extends Super_Test{
Super_sub(){
super();
System.out.println("This is sub class, object is created");
}
public static void main(String args[]){
new Super_sub();
}
}
From oracle documentation page:
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
You can also use super to refer to a hidden field (although hiding fields is discouraged).
Use of super in constructor of subclasses:
Invocation of a superclass constructor must be the first line in the subclass constructor.
The syntax for calling a superclass constructor is
super();
or:
super(parameter list);
With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called.
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error.
Related post:
Polymorphism vs Overriding vs Overloading

Is it overloading or overriding?

I have a code and I am not able to get why the output will be "Radial Tire with long".Can somebody help me to understand this code?
class Tyre {
public void front() throws RuntimeException {
System.out.println("Tire");
}
public void front(long a) {
System.out.println("Radial Tire with long");
}
}
class TestSolution extends Tyre {
public void front() {
System.out.println("Radial Tire");
}
public void front(int a) throws RuntimeException {
System.out.println("Radial Tire with int");
}
public static void main(String... args) {
Tyre t = new TestSolution();
int a = 10;
t.front(a);
}
}
front is not overridden in TestSolution, it is overloaded.
You can regard an overloaded function as a completely different function, like one with a different name.
So t.front(a) will call the one in Tyre, with an a implicitly converted to long.
So if we go with definitions
Overloading means methods with same name but with different number or order of parameters.
Overriding means method with same name with same number of parameters along with rules mentioned here
So in your case front method is overloaded in both the classes Tyre and TestSolution
method front() from Tyre class is overridden in class TestSolution.
no overriding in case of method front(long a) and front(int a).
There's no overriding taking place in your main.
t's static (compile-time) type is Tyre, so, since method overload resolution is determined by the compile-time type of the instance, the only front methods available for the compiler to choose from are those declared in the base class Tyre :
public void front()
public void front(long a)
Only the latter (public void front(long a)) matches the arguments of the call t.front(a), and that method is not overridden by the sub-class. Therefore Radial Tire with long is displayed.
Calling ((TestSolution)t).front(a); would invoke the sub-class's method - public void front(int a).
General rule: if I have a variable of one class I can access only methods and components defined in that class.
The only particular case is:
you have a component or method both in the super class and in the subclass (overriding)
you have a variable of the super class and an object of the subclass (your case)
In these cases you can follow the following rule:
for the components the type of the variable decides which to use
for the methods the type of the object does (late binding)
In your case as stated before the method is not overridden so you can't apply the last rule.
Lets understand the difference between overloading and overriding
Overloading:
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists
Overriding:
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.
Tyre declared front() method with long as parameter.
TyreSolution declared front() method with int as parameter.
Since the method signature is different, TyreSolution overloads Tyre's front() method
If you change signature of front() in TyreSolution to accept long value as input parameter instead of int, then TyreSolution overrides Tyre's front() method.
e.g. TestSolution class definition of front() method
public void front(long a) throws RuntimeException {
System.out.println("Radial Tire with long in TestSolution");
}
output:
Radial Tire with long in TestSolution

Override "private" method in java

There something ambiguous about this idea and I need some clarifications.
My problem is when using this code:
public class B {
private void don() {
System.out.println("hoho private");
}
public static void main(String[] args) {
B t = new A();
t.don();
}
}
class A extends B {
public void don() {
System.out.println("hoho public");
}
}
The output is hoho private.
Is this because the main function is in the same class as the method don, or because of overriding?
I have read this idea in a book, and when I put the main function in another class I get a compiler error.
You cannot override a private method. It isn't visible if you cast A to B. You can override a protected method, but that isn't what you're doing here (and yes, here if you move your main to A then you would get the other method. I would recommend the #Override annotation when you intend to override,
class A extends B {
#Override
public void don() { // <-- will not compile if don is private in B.
System.out.println("hoho public");
}
}
In this case why didn't compiler provide an error for using t.don() which is private?
The Java Tutorials: Predefined Annotation Types says (in part)
While it is not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with #Override fails to correctly override a method in one of its superclasses, the compiler generates an error.
is this because the main function is in the same class as the method "don"
No, it's because A's don() is unrelated to B's don() method, in spite of having the same name and argument list. private methods are hidden inside their class. They cannot be invoked directly by outside callers, such as main method in your case, because they are encapsulated inside the class. They do not participate in method overrides.
No, a private method cannot be overridden since it is not visible from any other class. You have declared a new method for your subclass that has no relation to the superclass method. One way to look at it is to ask yourself whether it would be legal to write super.func() in the Derived class.
You can't override a private method, but you can introduce one in a derived class without a problem. The derive class can not access the private method on the ancestor.
Since t is a on object of type B, calling don() method will invoque the method defined at B. It doesn't even know that there is a method named also don() at class A
private members aren't visible to any other classes, even children
You can't override a private method, but then again, you can't call it either. You can create an identical method with the same name in the child however.
public class A
{
private int calculate() {return 1;}
public void visibleMethod()
{
System.out.println(calculate());
};
}
public class B extends A
{
private int calculate() {return 2;}
public void visibleMethod()
{
System.out.println(calculate());
};
}
If you call A.visibleMethod() it prints out 1.
If you call B.visibleMethod() it prints 2.
If you don't implement the private calculate() method in B, it won't compile because the public method that calls it can't see the private method in A.

Using subclass' method in superclass

I have a class (called SubClass for simplicity) that extends SuperClass and implements IClass.
I know that you can call SuperClass' methods by using super.method(), but is it possible to call a method from SubClass which it implements from IClass?
Example:
public class SuperClass {
public void method(){
implementedMethod();
}
}
Subclass:
public class SubClass extends SuperClass implements IClass{
public void implementedMethod() {
System.out.println("Hello World");
}
}
IClass:
public interface IClass {
public void implementedMethod();
}
I would like to call SubClass' implementedMethod() (Which it gets from IClass) from SuperClass
How would I go about doing that?
You can make the super class abstract:
public abstract class SuperClass implements IClass {
public void method(){
implementedMethod();
}
}
Given the types above, anExpressionOfTypeSubClassOrIClass.implementedMethod() must be used. Note that the Type of an expression - the view it provides - must have the method intended to be used. In this case, an expression of type SuperClass cannot be used here because it has no declared implementedMethod member.
One approach - and arguably the preferred approach - is to use abstract methods. Even though abstract methods are not strictly required for Polymorphism they describe scenarios such as this where a subclass should provide the implementation. (The abstract methods could be replaced with empty method expecting - but not requiring - to be overridden in sublcasses, but why not use abstract for its designed purpose?)
abstract class SuperClass implements IClass {
// Don't implement this, but declare it abstract
// so that we can conform to IClass as well
public abstract void implementedMethod();
public void method () {
// Now this object (which conforms to IClass) has implementedMethod
// which will be implemented by a concrete subclass.
implementedMethod();
}
}
This has the "negative" aspects that SuperClass cannot be directly instantiated (it is abstract, after all) and that SuperClass must implement (or, as shown, delegate out via abstract) the expected signature. In this case I also chose to make SuperClass implement IClass even though it's not strictly required because it guarantees that the SuperClass and all subclasses can be viewed as an IClass.
Alternatively, remember that Types of Expressions are just views of objects and are not necessarily the same as the actual Concrete Type of object. While I would advise against using the following code because it loses some type-safety, I think it shows the important point.
class SuperClass {
public void method () {
// We try to cast and NARROW the type to a
// specific "view". This can fail which is one
// reason why it's not usually appropriate.
((IClass)this).implementedMethod();
}
}
class SubClass extends SuperClass implements IClass {
// ..
}
class BrokenSubClass extends SuperClass () {
}
// OK! Although it is the SAME OBJECT, the SuperClass
// method can "view" the current instance (this) as an IClass
// because SubClass implements IClass. This view must be
// explicitly request through a cast because SuperClass itself
// does not implement IClass or have a suitable method to override.
(new SubClass()).method();
// BAD! ClassCastException, BrokenSubClass cannot be "viewed" as IClass!
// But we didn't know until runtime due to lost type-safety.
(new BrokenSubClass()).method();
The only way to call that method would be to create an object of type SubClass (in SuperClass) and call subClassInstance.implementedMethod().
I also want to stress that this is very inelegant. As stated in a comment on your question, you should reconsider your class designs if your superclass needs to call a subclass method.

why should we widen the accessibility of overridden methods?

why should we widen the accessibility of overridden methods ? If the super class has a protected method and subclass has same method with public. Why should happen?
It's a different method! Subclasses don't inherit private methods! So you're not "overriding" at all. You are simply DEFINING a method with the same name as the private method in the superclass.
class A
{
private void myMethod() { }
}
class B extends A
{
public void myMethod() { } // a completely different method. Has nothing to do with the above method. It is not an override.
}
Because in an object hierarchy, JVM will always run the Overriden method. If your overriden method is not accessible, then it is useless.
public class A{
void A(){}
}
public class B extends A{
private void A(){} //this makes no sence and its impossible
PSV main(String ..){
A a = new B();
a.A(); //error as JVM cannot call overriden method which is private.
}
}
Methods declared as private or static can not be overridden!
Annotation #Override indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.
Use it every time you override a method for two benefits. This way, if you make a common mistake of misspelling a method name or not correctly matching the parameters, you will be warned that you method does not actually override as you think it does. Secondly, it makes your code easier to understand because it is more obvious when methods are overwritten.
And in Java 1.6 you can use it to mark when a method implements an interface for the same benefits.

Categories