Метод, чтобы взять несколько типов - PullRequest
1 голос
/ 25 августа 2011

В настоящее время я работаю с конструктором, который принимает объект типа Затем я проверяю его тип на основе instanceof

Public MyClass (Object obj)
{
if(obj instanceof CusClass1){
CusClass1 myObject = (CusClass1) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
if(obj instanceof CusClass2){
CusClass2 myObject = (CusClass2) obj;
globalVar1 = myObject.getAttrib1();
globaVar2 = myObject.getAttrib2();
}
}

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

Ответы [ 6 ]

4 голосов
/ 25 августа 2011

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

public MyClass(CusClass1 myObject) {
    globalVar1 = myObject.getAttrib1();
    globalVar2 = myObject.getAttrib2();
}

public MyClass(CusClass2 myObject) {
    globalVar1 = myObject.getAttrib1();
    globalVar2 = myObject.getAttrib2();
}

Имеют ли CusClass1 и CusClass2 одинаковые методы getAttrib1() и getAttrib2()? Затем рассмотрите возможность создания интерфейса, который реализуют оба этих класса, и создайте конструктор, который принимает объект, реализующий этот интерфейс:

public interface Attribs {
    String getAttrib1();
    int getAttrib2();
}

public class CusClass1 implements Attribs {
    // ...
}

public class CusClass2 implements Attribs {
    // ...
}

public class MyClass {
    // You can now pass anything that implements interface Attribs
    public MyClass(Attribs myObject) {
        globalVar1 = myObject.getAttrib1();
        globalVar2 = myObject.getAttrib2();
    }
}
0 голосов
/ 25 августа 2011

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

В противном случае, да, вы можете использовать и метод init следующим образом:

public class MyClass {

    public MyClass (Object obj) {
        if (obj instance of CusClass1) {
         init((CusClass1) obj);
        } else if (obj instanceof CucClass2) {
         init((CusClass2) obj);
        }

        // shared initialization code
    }

    public void init(CusClass1 obj) {
        globalVar1 = obj.getAttrib1();
        globaVar2 = obj.getAttrib2();
    }

    public void init(CusClass2 obj) {
        globalVar1 = obj.getAttrib1();
        globaVar2 = obj.getAttrib2();
    }
}
0 голосов
/ 25 августа 2011

Если вы можете изменить CusClass1 и CusClass2, вы можете создать интерфейс

 public interface AttributeProvider {
     Object getAttrib1();  // or whatever type getAttrib1 should return
     Object getAttrib2();
 }

и затем убедитесь, что CusClass1 и CusClass2 реализуют этот интерфейс:

 public class CusClass1 implements AttributeProvider {
     ...
 }

тогда вы можете иметь конструктор только с этим интерфейсом:

 public MyClass(AttributeProvider myObject) {
     globalVar1 = myObject.getAttrib1();
     globaVar2 = myObject.getAttrib2();
 }

Таким образом, вам не придется изменять MyClass, если вы создадите новый CusClass3, который также должен использоваться в MyClass

0 голосов
/ 25 августа 2011

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

Если все пользовательские классы имеют необходимые атрибуты / методы с одинаковыми именами (например, attrib1 и attrib2 в вашем примере), отражение будет проще. Все, что вам нужно, это набор потенциальных имен классов и имен атрибутов для запроса.

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

0 голосов
/ 25 августа 2011

Не повторять код и не разыгрывать.Создайте 2 конструктора: один принимает CusClass1, второй CusClass2.Реализуйте их отдельно.

0 голосов
/ 25 августа 2011

Вместо этого создайте один метод для каждого типа объекта.

public MyClass(CusClass1 obj) {
    field1 = obj.getProperty1();
    field2 = obj.getProperty2();
}

public MyClass(CusClass2 obj) {
    field1 = obj.getOtherProperty1();
    field2 = obj.getOtherProperty2();
}
...