Как лучше всего расширить функциональные возможности класса?


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

public class TaskHelper extends Task
{
    public void getName()
    {
        ....
    }

    // more additional functionality
}

Итак, я начинаю использовать это, и когда у меня есть объект task, и опускается до TaskHelper, я получаю ClassCastException. Поэтому я понимаю, что не могу унывать, и я пытаюсь создать копию конструкции что-то вроде

public class TaskHelper extends Task
{
    TaskHelper(Task t)
    {
        Task(t);
    }
}

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

4 2

4 ответа:

Я не могу изменить задачу, потому что это сторонний класс

Task это внешняя зависимость. Вместо того чтобы расширять его, абстрагируйте его. Что-то вроде этого:

public class TaskHelper
{
    private Task task;

    public TaskHelper() {
        task = new Task();
    }

    // expose methods to delegate functionality to the private member
}

Это позволяет отделить ваш код от кода третьей стороны. Это приносит ряд преимуществ:

  • вы можете упростить интерфейс для стороннего компонента, предоставив только необходимую функциональность или переименовав функциональность в соответствии с вашим доменным языком
  • вы можете имейте TaskHelper реализовать интерфейс, который может быть легко высмеян для модульного тестирования или заменен другими реализациями задачи
  • вы можете объединить функциональность с другими связанными вещами и расширить компонент, все еще инкапсулируя его в этот объект

Если я правильно понял ваш вопрос, у вас есть объект Task где-то в коде и вы хотите предоставить ему дополнительную функциональность, расширив сам класс Task. Ну, для меня это звучит так, как будто вам нужен какой-то класс обертки. Я бы создал TaskHelper следующим образом:

public class TaskHelper {

    private Task taskObject;
    private String name;
    //Additional variables

    public TaskHelper(Task t) {
        taskObject = t;
    }

    public Task getTaskObject() {
        return taskObject;
    }

    //Setters, Getters and other methods working on the Task 
    object and additional variables

}

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

Если вам нужна возможность обработайте TaskHelper как обычный объект задачи, вам нужно расширить класс задачи, но это тоже легко. Просто создайте класс TaskHelper, как вы написали, и вызовите метод super () (который вызывает конструктор суперклассов..) вместо вашей задачи (Т). Убедитесь,что вы также предоставляете всю информацию, необходимую конструктору задачи в конструкторе TaskHelper.

Надеюсь, это вам немного помогло.

Лучший дизайн-это использование композиции.
public class TaskHelper { Task task; }

Вы сможете использовать любой вид задачи, используя этот подход.

Здесь задача должна быть интерфейсом.

Согласно Вашему вопросу Class Task - это класс 3-й стороны, где вы не можете изменить его реализацию. Вы пробовали, можете ли вы "увидеть" методы Task из TaskHelper после того, как вы расширяете Task?

class TaskHelper extends Task
{

}

Приведенный выше код неявно наследует все методы и члены от Task до TaskHelper. Таким образом, вам больше не нужно явно / вручную пытаться расширить методы суперкласса.

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

Кое-что дополнение: Если вам нужно получить доступ к любому из членов класса super или вызвать конструктор из класса super, вы можете использовать ключевое слово super.

Пример использования "супер":

class A //A is super Class
{
   private int a;
   public A(int a)
   {
      this.a = a;
   }
}

class B extends A //B is sub Class
{
   private int b;
   public B(int a, int b) //a inherited from Class A
   {
      super(a); //use "super" to call the constructor from super class
      this.b = b;
   }
}