2014-10-07 7 views
1

У меня есть абстрактный суперкласс с некоторыми реализованными методами.Методы скрытия в подклассе

Можно ли скрыть методы из этого суперкласса в подклассе, наследующем от этого суперкласса? Я не хочу, чтобы некоторые методы были видны из суперкласса в некоторых подклассах. И последнее, но не менее важное: возможно ли изменить количество аргументов для метода в подклассе, который имеет одно и то же имя в суперклассе?

Предположим, что у нас есть метод public void test(int a, int b) в суперклассе, но теперь мне нужен метод public void test(int a) в подклассе, который вызывает функцию суперкласса, а метод из суперкласса больше не виден.

+0

Удалось ли мне ответить на ваш вопрос? Или что-то неясно? – aioobe

ответ

4

Можно ли скрыть методы этого суперкласса в качестве подкласса наследуемых от этого суперкласса?

Если вы сделаете метод рядовым в супер класс, он не будет виден в подклассе (или любому другому).

Если вам нужен метод в базовом классе, который должен быть общедоступным, в нем нет возможности скрывать его в подклассе, например, переопределяя его с помощью частной реализации. (Вы не можете «уменьшить видимость», то есть перейти от, например, публичного или защищенного к закрытому в подклассе.)

Наилучшим решением является, возможно, переопределение метода и сброс для исключения во время выполнения, такого как UnsupportedOperationException.

можно ли изменить количество аргументов для метода подкласса, который имеет такое же имя в суперкласса?

Нет, вы не можете изменить подпись. Вы можете создать еще один метод с тем же именем и другим числом аргументов, но это будет другой (перегруженный) метод, и метод в базовом классе все равно будет видимым.

+0

Обходной путь заключается в том, чтобы сделать метод «защищенным» в суперклассе, а затем иметь две реализации. Один только делает метод 'public' (т. Е. Предоставляет доступ к родительскому API), в то время как другой создает новые методы, которые вызывают родительский API. Второй тип несколько скрывает родительский API (но подклассы все еще могут видеть их). –

+1

Ответ на второй вопрос правильный, но я думаю, что он сформулирован как вводящий в заблуждение. Полностью допустимо перегрузить имя метода, изменив количество и тип аргументов. Более того, нет ограничений на квалификатор доступа для перегруженного имени метода (если подпись не соответствует другому унаследованному методу). Тем не менее, метод суперкласса все еще будет видимым. –

+0

Это не * изменение * количества аргументов, то есть * добавление * другого метода с другим числом аргументов. – aioobe

1

Вы не можете полностью скрыть метод из суперкласса, его всегда можно вызвать, например.

MyBase o = new MyClass(); 
    o.test(1, 2); 

Однако, вы можете переопределить метод определенным образом:

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) { ; } 
} 
0

Java не поддерживает снижения видимости.

Существует способ, чтобы сделать что-то вроде этого, но это сложно:

  1. Вы должны создать интерфейс для родительского типа. Этот интерфейс не нуждается в методах.
  2. Вы создаете новый, новый тип Delegate, который реализует метод public void test(int a, int b)
  3. Вы удаляете текущий родительский тип.
  4. Вы создаете два новых типа, которые реализуют интерфейс.Один из делегатов вызывает звонок test(a,b) - Delegate, а другой создает новый метод test(a), который в конечном итоге использует экземпляр Delegate.

Так что тип, который реализует старый код, никогда не виден во внешнем мире (это может быть частный пакет пакета).

+0

Конечно, тогда объекты новых типов больше не будут экземплярами базового класса. –

+0

Вот почему новые типы реализуют один и тот же интерфейс. Как я уже сказал, это не приятно, понятно и т. Д. –

+0

Извините - в моем комментарии не было ясно. У исходного базового класса были определенные методы, а новые типы - нет, что делает их непригодными в ситуациях, когда клиентский код написан для использования этих методов базового класса. Вы предлагаете хорошую архитектуру для другой проблемы, чем OP, похоже, сталкивается. –

1

Нет, вы не можете скрыть открытый метод в дочернем модуле, например, создав там метод private.

Причина в том, что, имея экземпляр дочернего класса, вы всегда можете отнести его к базовому классу и вызвать метод там.

Так что это логично. Либо перепроектируйте иерархию классов, либо создайте новый класс, если это становится слишком уродливым API.

Однако вы можете переопределить метод и

/** 
* 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); 
} 

Перегрузки метод можно: такое же имя, различные типы параметров.

Смежные вопросы