4

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.

dbc
  • 104,963
  • 20
  • 228
  • 340
machinery
  • 5,972
  • 12
  • 67
  • 118

4 Answers4

7

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.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • A workaround is to make the method `protected` in the superclass and then have two implementations. One just makes the method `public` (i.e. grants access to the parent API) while the other creates new methods which call the parent API. The second type somewhat hides the parent API (but subclasses can still see them). – Aaron Digulla Oct 07 '14 at 13:11
  • 1
    The answer to the second question is correct but I think the way it is worded is misleading. It is entirely permissible to overload the method name by changing the number and type of arguments. Moreover, there is no restriction on the access qualifier for the overloaded method name (provided the signature doesn't match another inherited method). However, the superclass method will still be visible. – Ted Hopp Oct 07 '14 at 13:14
  • That is not *changing* the number of arguments, that is *adding* another method with a different number of arguments. – aioobe Oct 07 '14 at 13:19
  • I agree. However, your wording may suggest to a novice that overloading the method name is not allowed. – Ted Hopp Oct 07 '14 at 13:28
  • Much better. It wouldn't hurt to reiterate that the base class method will still be visible. – Ted Hopp Oct 07 '14 at 13:31
1

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) { ; }
}
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
1

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.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

Java doesn't support reducing visibility.

There is a way to do something like this but it's complex:

  1. You need to create an interface for the parent type. This interface doesn't need to have methods.
  2. You create another, new type Delegate which implements the method public void test(int a, int b)
  3. You delete the current parent type.
  4. 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).

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • Of course, then objects of the new types will no longer be instances of the base class. – Ted Hopp Oct 07 '14 at 13:33
  • That's why the new types implement the same interface. As I said, it's not nice, clear, etc. – Aaron Digulla Oct 07 '14 at 13:35
  • Sorry--I wasn't clear in my comment. The original base class had certain methods and the new types don't, making them unusable in situations where client code is written to use those methods of the base class. You're proposing a good architecture for a different problem than OP seems to be facing. – Ted Hopp Oct 07 '14 at 13:38
  • Move the methods you share into the interface. As I said, it's a clumsy solution but that depends on what OP really wants to achieve. – Aaron Digulla Oct 07 '14 at 13:40