Нестатический метод create-new-from? - PullRequest
4 голосов
/ 10 января 2012

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

class A {
    B toB() {...}
    static A fromB(B b) {...}
}

или

class B {
    void save(File f) {...}
    static B load(File f) {...}
}

Раньше я думал, что это хороший и простой подход, но в последнее время меня раздражает статичность метода convert-from, например, если я хочу определить интерфейс для типов, которые могут быть преобразованы в и из - B:

interface ConvertableToAndFromB {
    B toB();
    // ?
}

Итак, есть ли элегантный способ сделать это без преобразования - из статического, кроме перехода на Smalltalk?

EDIT

Чтобы уточнить, я понимаю, что могу добавить нестатический метод в интерфейсе, например ::

interface ConvertableToAndFromB {
    B toB();
    void fromB(B b);
}

или, если я хочу разрешить неизменяемые типы (спасибо Stripling):

interface ConvertableToAndFromB<T implements ConvertibleToAndFromB<T>> {
    B toB();
    T fromB(B b);
}

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

A a = new A();
a.fromB(b);

или (для неизменяемого):

A a = new A();
a = a.fromB(b);

это то, чего я пытаюсь избежать (но без другого решения). Я просто надеюсь, что есть более хороший путь.

Ответы [ 4 ]

3 голосов
/ 10 января 2012

Вы должны сделать свой интерфейс рекурсивно универсальным. Я считаю, что синтаксис такой:

interface ConvertibleToAndFromB<T implements ConvertibleToAndFromB<T>>{
    B toB();
    T fromB(B b);
}

class A implements ConvertibleToAndFromB<A> {
    B toB() {...}
    A fromB(B b);
}

Создание таких вещей, как это, имеет очевидные преимущества. Тем не менее, это означает, что вы должны быть осведомлены о фактическом типе, который вы хотите, когда вы звоните fromB. У этого подхода есть свои преимущества и недостатки.

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

Converter<A, B> converter = converterFactory.get<A, B>(A.class, B.class);
B b = converter.from(a);
1 голос
/ 11 января 2012

Часто метод fromB реализуется как конструктор копирования.Например,

public class A
{
  public A(B b)
  {
    this.someValue = b.someOtherVariable;
  }
}

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

0 голосов
/ 11 января 2012

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

например, когда вы конвертируете массив в список, вы не делаете arr.asList (), скорее вы используете Arrays.asList (arr)

0 голосов
/ 10 января 2012

В вашем сценарии я сделаю это так:

interface ConvertableToA {
    A toA() {...}
}


interface ConvertableFromA {
    Object fromA(A a) {...}
}


class MyConvertableClass implements ConvertableToA, ConvertableFromA {
    ...
}
...