Reputation: 1517
I have two similar object in Java / Groovy, lets say:
class a {
Date creation
}
class a {
String creation
}
and in my program, there is a switch that determines what object should I use (Groovy
code):
def obj
if(/* certain criteria for a */) {
obj = new package.foo.a()
// ...
// Or some other process aside from initialization.
}
else if(/* certain criteria for the another a */) {
obj = new package.bar.a()
// ...
// Or some other process aside from initialization.
}
else {
obj = null
}
Later in the code, I need to determine the process I should perform based on the type of the property creation
:
if(obj.creation instanceof Date) {
obj.creation = new Date()
}
else if(obj.creation instanceof String) {
obj.creation = '1995-08-17'
}
The above code doesn't work. Is there someway to do this? Of course I can always do the following if the property's datatype is not obtainable:
if(obj instanceof package.foo.a) {
obj.creation = new Date()
}
else if(obj instanceof package.bar.a) {
obj.creation = '1995-08-17'
}
Upvotes: 2
Views: 150
Reputation: 9885
Sometimes depending on an object's type in necessary, but it should be avoided because it makes the code more fragile. You could end up with type checking littered all over your code base. In your case, you can delegate the class-specific behaviour to the class itself. Here's an example:
class A {
Date creation
void initializeCreationDate() {
creation = new Date()
}
}
/* I'm using a different class name to make this
* example self-contained.
*/
class B {
String creation
void initializeCreationDate() {
creation = '1995-08-17'
}
}
def obj
def condition = true
if(condition) {
obj = new A()
} else {
obj = new B()
}
obj.initializeCreationDate()
In the example, the two classes become responsible for setting their own creation date. This helps keep the code nice and neat.
You can still achieve the same effect even when you're unable to (or do not want to) modify the source code of the two classes. In such a case, you can use a mixin to add the initializeCreationDate() method. Like this:
class A {
Date creation
}
/* I'm using a different class name to make this
* example self-contained.
*/
class B {
String creation
}
class DateInitializer {
static void initializeCreationDate(A object) {
object.creation = new Date()
}
static void initializeCreationDate(B object) {
object.creation = '1995-08-17'
}
}
def obj
def condition = true
if(condition) {
obj = new A()
} else {
obj = new B()
}
obj.metaClass.mixin DateInitializer
obj.initializeCreationDate()
Upvotes: 1
Reputation: 4472
It doesn't work because creation is null. null is not an instance of any objects.
You have to use reflection API to get a field type and then use Class.isAssignableFrom()
to check type.
if(String.class.isAssignableFrom(a.class.getDeclaredField("creation").getType()){
...
}
I edited it to make the code compiles :)
Upvotes: 0
Reputation: 3034
You could try getting the class
of the object and checking if it has the same class
as whichever type you are checking for:
if(obj.creation.getClass().equals(Date.class)) {
obj.creation = new Date();
}
else if(obj.creation.getClass().equals(String.class)) {
obj.creation = "1995-08-17";
}
Upvotes: 2