Can a Subclass Override a Function and Make More Restrictive Return

Why derived class overriding method should not be more restrictive than base class in java?

The point is that a caller who only knows about your superclass should still be able to use any instance of the subclass that it's given. Consider this situation:

public class Super
{
public void print()
{
System.out.println("Hello!");
}
}

public class Sub extends Super
{
@Override
void print() // Invalid
{
System.out.println("Package access");
}
}

Now from a different package, imagine we had:

public void printSuper(Super x)
{
x.print();
}

and we called that with:

printSuper(new Sub());

What would you expect that to do? You're overriding the method, so it should print "package access" - but then that means you're calling a package access method from a different package...

Basically, this is just one example of the Liskov Substitution Principle in action. You should be able to treat any instance of a subclass as an instance of the superclass, and it's hard to see how that fits in with making things more restrictive in a subclass.

Can a subclass override a method and have different parameters?

What you want to do is called overloading a method. It is doable and occurs often. Play with the fiddle here. Java is similar.

public class Parent
{
public virtual string HelloWorld()
{
return "Hello world";
}

public string GoodbyeWorld()
{
return "Goodbye world";
}
}

public class Child : Parent
{
// override: exact same signature, parent method must be virtual
public override string HelloWorld()
{
return "Hello World from Child";
}

// overload: same name, different order of parameter types
public string GoodbyeWorld(string name)
{
return GoodbyeWorld() + " from " + name;
}
}

public class Program
{
public static void Main()
{
var parent = new Parent();
var child = new Child();
Console.WriteLine(parent.HelloWorld());
Console.WriteLine(child.HelloWorld());
Console.WriteLine(child.GoodbyeWorld());
Console.WriteLine(child.GoodbyeWorld("Shaun"));
}
}

When overriding a method, why can I increase access but not decrease it?

It's a fundamental principle in OOP: the child class is a fully-fledged instance of the parent class, and must therefore present at least the same interface as the parent class. Making protected/public things less visible would violate this idea; you could make child classes unusable as instances of the parent class.

Overriding a method with different return types in java?

You can return a different type, as long as it's compatible with the return type of the overridden method. Compatible means: it's a subclass, sub-interface, or implementation of the class or interface returned by the overridden method.

And that's logical. If a method returns an Animal, and your derived class returns a Cow, you're not breaking the contract of the superclass method, since a Cow is an Animal. If the derived class returns a Banana, that isn't correct anymore, since a Banana is not an Animal.

Can an overriding method have a different access specifier from that in the base class?

It is possible to relax the restriction, but not to make it more restrictive:

public abstract class A {
protected void method();
}

public class B extends A {
@Override
public void method(){ // OK
}
}

public class C extends A {
@Override
private void method(){ // not allowed
}
}

Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.

I would recommend using interfaces to selectively expose or hide the method:

public interface WithMethod {
// other methods
void method();
}

public interface WithoutMethod {
// other methods
// no 'method()'
}

public abstract class A {
protected void method();
}

public class B extends A implements WithMethod {
@Override
public void method(){
//TODO
}
}

public class C extends B implements WithoutMethod {
// no 'method()'
}

... then only work with the instances through the interfaces.

Overloading overridden method am I overloading parent or sub-class method

You override something that is inherited, so B.a() overrides A.a(). Overriding means to redefine.

Overloading is when your class have more than one definition of the same method name (each with different argument types). In B, the name a is overloaded. There is B.a() and B.a(int x).

Some of the definitions might be inherited. So if you remove B.a(), the class B would still have a method a() since it inherits it from A. And the method name a would still be overloaded in B.

Why can't I change the return type of overriden methods (other than covariant return type)?

Let's use a simple example to explain why it doesn't make any sense to change the return type of an overridden method.

Suppose I have a Car object:

class Car {

public String getModel() {
return "Awesome Car";
}
}

This Car class has a method getModel() that returns a String.

Now, you have another class that extends Car and overrides the getModel() method:

class DumbCar extends Car {
@Override
public Hamburger getModel() {
return new Hamburger();
}
}

Suddenly, you have a major problem. You create a DumbCar object and since you know that all Car objects can tell you their model, you try to get that model:

DumbCar myCar = new DumbCar();
System.out.println(myCar.getModel());

The output is A juicy Big Mac!

Does that make any sense to you? You cannot drive a Big Mac.


Java is a heavily type-safe language. When you write a statement asking to getModel(), you need to be absolutely, 100% positive, that the data you get back is what you were expecting. Java enforces that expectation.



Related Topics



Leave a reply



Submit