Динамическая подстановка реализации toString () базового класса - PullRequest
0 голосов
/ 16 декабря 2009

У меня есть класс А с

public String toString() {
}

способ.

Это компилируется. Кроме того, у меня есть несколько реализаций этого метода в качестве тела метода. В этой реализации используются поля А.

Я хочу иметь возможность динамически подставлять содержимое метода toString () с такой или такой реализацией. Дело в том, что мне нужны поля А. в реализации.

Должен сказать, я не могу создать подклассы A. Я должен использовать только этот класс.

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


Возможно, самое простое решение - использовать переменную-флаг и проанализировать ее, прежде чем вызывать тот или иной метод, или даже поместить все в toString и использовать switch. Но что, если A ничего не знает о своей реализации? Можно ли их развязать - класс A и его реализации toString?

Ответы [ 4 ]

2 голосов
/ 16 декабря 2009

Полагаю, теоретически вы могли бы создать несколько классов с именем A с различными реализациями метода toString(), а затем динамически загружать их с разными загрузчиками классов и т. Д. Однако, с точки зрения JVM, они будут разными классами вы не сможете убедить JVM по-другому. Таким образом, вы не будете в конечном итоге "выиграть".


Более практичный подход может выглядеть примерно так:

class A {
    Formatter f;
    A(Formatter f) {
        this.f = f;
    }
    ...
    @Override 
    public String toString() {
        return f.format(this);
    }
}

и написать множество классов для реализации интерфейса Formatter.

1 голос
/ 16 декабря 2009

Как насчет использования шаблона декоратора ?

шаблон декоратора - это шаблон проекта, который позволяет добавлять новое / дополнительное поведение к существующему объекту dynamicicall

(хотя я не уверен, соответствует ли это изменениям, которые вы можете или не можете внести в A)

Редактировать : Если вы можете категорически использовать только поля A * (а не методы доступа к полю (метод получения)), то шаблон Decorator, вероятно, не будет работать. По этому вопросу трудно сказать, так ли это.

1 голос
/ 16 декабря 2009

Я не понимаю, что делать, и что вы подразумеваете под «динамической заменой», но вы можете добавить к A дополнительное поле, которое вы используете для переключения реализаций. Что-то вроде следующего. Затем вы можете «динамически» переключаться на разные реализации, изменяя эту переменную режима.

public String toString() {
  switch(mode) {
    case 1: return toStringImplementation1();
    case 2: return toStringImplementation2();
    /* ... */
    default: return super.toString();
  }
}

Что касается вашего последующего вопроса о разделении: конечно, это возможно. Тем не менее, вы сказали, что реализации напрямую зависят от полей A, и вы, вероятно, не хотите открывать их миру. Я также не вижу никакого преимущества перед разделением реализаций на внутренние классы вместо простых методов, но опять же, я все еще не знаю, чего вы пытаетесь достичь.

0 голосов
/ 16 декабря 2009

Это домашняя работа? Если это так, вы должны пометить его как таковой.

То, что обеспечит лучшее решение, зависит от того, чего вы хотите достичь. Если вам нужно несколько строковых представлений объекта, вы можете ввести несколько версий toString, например:

public String toString() {
}

public String toXmlString() {
}

public String toHumanFriendlyString() {
}

Если, с другой стороны, у вас есть методы, подобные вышеописанным, реализованные в вашем объекте, и вы хотите установить формат вывода, вы можете использовать тип вывода:

public String toString() {
    switch (outputType) {
    default:
         return "Unknown output type for: " + toDebugString();
    case TYPE_DEBUG:
         return toDebugString();
    case TYPE_XML:
         return toXmlString();

}

Если вам нужно, чтобы реализация была настраиваемой из других частей вашего кода, используйте шаблон плагина:

interface Stringable {
    String toString(A a);
}

class A {

    Stringable impl = this;

    void setStringable(Stringable s) {
         impl = s;
    }

    String toString() {
         return impl.toString(this);
    }

    String toString(A a) {

          return "A a";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...