1

I currently am working with a constructor which takes in of type object I am then testing it's type based on 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();
}
}

Can this be offset to an initalise method called from within the constructor. The major problem is in the casting of the Object. I was always under the impression that repeated code is bad code. Can this be made more elegant?

Will
  • 8,246
  • 16
  • 60
  • 92

6 Answers6

4

A much better, more type-safe design would be to create multiple overloaded constructors. You would then not need any casts, and you would make it impossible to construct an object by passing it an object of an inappropriate type.

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

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

Do CusClass1 and CusClass2 have the same getAttrib1() and getAttrib2() methods? Then consider creating an interface that both these classes implement, and create a constructor that takes an object that implements that interface:

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();
    }
}
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • they have the same methods unfortunately they are not within my scope to edit :( – Will Aug 25 '11 at 11:08
  • And whether they are based on an interface isn't clear? Or you know they don't implement an interface? – Wivani Aug 25 '11 at 11:22
0

Create one method for each type of the object instead.

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

public MyClass(CusClass2 obj) {
    field1 = obj.getOtherProperty1();
    field2 = obj.getOtherProperty2();
}
Christoffer Hammarström
  • 27,242
  • 4
  • 49
  • 58
0

Do not repeat code and do not cast. Create 2 constructors: one accepts CusClass1, second CusClass2. Implement them separately.

AlexR
  • 114,158
  • 16
  • 130
  • 208
0

If you have many such custom classes, it may be better to use reflection and/or annotations (and especially if not all of them are known at compile time, this may be the only solution).

If all the custom classes have the necessary attributes/methods with the same names (like attrib1 and attrib2 in your example), reflection is the easier. All you need is a set of potential class names, and the names of the attributes to query.

If, however, the attribute names may vary, you may consider using annotations to mark the desired source attributes in each class.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
0

If you can modify CusClass1 and CusClass2, you could create an interface

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

and then ensure that CusClass1 and CusClass2 implement this interface:

 public class CusClass1 implements AttributeProvider {
     ...
 }

then you can have a constructor with just that interface:

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

That way, you won't have to modify MyClass if you create a new CusClass3 which should also be used in MyClass

beny23
  • 34,390
  • 5
  • 82
  • 85
0

If your constructor can be modified to accept CusClass1 and CusClass2 rather than Object, then you can follow one of the solutions provided in other answers.

Otherwise, yes, you can use and init method like this:

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();
    }
}
Behrang
  • 46,888
  • 25
  • 118
  • 160
  • Yes, you're right. I thought CusClass1 and CusClass2 have different attributes. – Behrang Aug 25 '11 at 11:27
  • Well all the other solutions have similarly repeated code, with the exception of the one suggesting the use of interfaces. – Behrang Aug 25 '11 at 11:28
  • True. Unless the interface is an acceptable solution, some Design Pattern might come in handy. – Wivani Aug 25 '11 at 11:46