Подтвердить что ты не робот

Как продлить окончательный класс в Java

Вот моя проблема, с которой я сейчас сталкиваюсь. У меня есть класс, скажем Foo, и этот класс определяет метод с именем getBar, который возвращает экземпляр Bar. Класс Bar определяется внутри Foo и объявляется public static final. Я хочу, чтобы определить класс MyFoo, который расширяет Foo, но я также хочу расширить Bar с помощью MyBar, добавив свои собственные функции (методы, свойства и т.д.). Я также хочу, чтобы getBar возвращал MyBar.

Задача Bar является окончательной. Вот иллюстрация того, что я хочу сделать:

public class Foo {

  Bar bar = new Bar();

  public Bar getBar(){
      return bar;
  } 

   ....

   public static final class Bar {

    } 
}

Что я хочу сделать:

public class MyFoo extends Foo {


   public MyBar getBar(){ // here I want to return an instance of MyBar

   }

  public static final class MyBar extends Bar { // That impossible since Bar is final

  } 
}

Как я могу это достичь?

[EDIT] Я добавляю более подробные сведения к моему вопросу. Я действительно разрабатываю плагин для Jenkins и после поиска, я понимаю, что есть плагин, который предлагает базовые функции, которые я хочу сделать, Foo и Bar. Я хочу настроить Foo и Bar, чтобы он соответствовал моим потребностям. Foo является основным классом плагина и расширяет класс Builder. Foo определяет метод под названием perform, который содержит все операции для выполнения сборки. Bar содержит операции для целей конфигурирования, а Foo - это Bar для получения этих сведений.

Итак, что я хочу сделать, это расширить Foo с помощью MyFoo и добавить некоторые конфигурации с помощью MyBar. И, как вы видите, MyFoo нужно будет получить эти конфигурации, вызвав getBar();

Во-вторых, я не контролирую instanciation MyFoo и MyBar

Что блокирует меня, я не могу расширить Bar. Как я могу это достичь?

4b9b3361

Ответ 1

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

(Трудно дать более конкретный совет, не зная больше о реальной цели здесь - разработке общей системы.)

Ответ 2

Вы не можете расширить класс, объявленный final. Однако вы можете создать промежуточный класс, называемый Wrapper. Этот Wrapper будет в основном содержать экземпляр исходного класса и предоставляет альтернативные методы для изменения состояния объекта в соответствии с тем, что вы хотите сделать.

Конечно, это не даст доступ к закрытым и защищенным полям класса final, но вы можете использовать его методы getters и seters в сочетании с новыми методами и полями, которые вы объявили в классе Wrapper, чтобы получить результат, который вы хотите или что-то относительно близко.

Другим решением является не объявлять final класс, если для этого нет веской причины.

Ответ 3

Вы не можете расширить класс final - цель ключевого слова final.

Однако существуют (по крайней мере) два рабочих процесса:

  • Класс находится в проекте Jenkins, который является открытым исходным кодом, поэтому вы можете просто загрузить проект, внести изменения, которые вы хотите в класс, и перестроить банку
  • Отчасти из-за взлома, но вы можете использовать библиотеку, например Javassist, чтобы заменить реализацию класса в памяти

Ответ 4

Вы не можете расширять заключительные классы, то есть точку объявления классов final. Вы можете определить интерфейс, который наследуется как для окончательного класса, так и для класса-оболочки, который делегирует вызовы завершенному окончательному классу. Поэтому возникает вопрос, почему сделать класс окончательным на первом месте.

Ответ 6

Например, мы не можем добавить StringBuffer в Collection TreeSet, потому что TreeSet не является дочерним элементом интерфейса Comparable:

public class Main(){
public static void main(String[] args){
   TreeSet treeSetSB = new TreeSet();
   treeSetSB.add(new StringBuffer("A"));  //error, Comparable is not implemented
}

Но мы можем использовать оболочку для реализации Comparable:

class myWrap implements Comparable{
    TreeSet treeset;
    public myWrap() {
        this.treeset=new TreeSet<>();

    }
    public TreeSet getTreeset() {
        return treeset;
    }
    public void setTreeset(TreeSet treeset) {
        this.treeset = treeset;
    }
}


public class Main(){
public static void main(String[] args){

   myWrap myWrap =new myWrap();
   TreeSet myTrs  =myWrap.getTreeset();
   myTrs.add("b");   // no error anymore
   myTrs.add("a");
   myTrs.add("A");
   System.out.println(myTrs);
}