问题
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?
回答1:
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();
}
}
回答2:
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();
}
回答3:
Do not repeat code and do not cast. Create 2 constructors: one accepts CusClass1, second CusClass2. Implement them separately.
回答4:
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
回答5:
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();
}
}
回答6:
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.
来源:https://stackoverflow.com/questions/7189132/a-method-to-take-a-number-of-types