3

I'm trying to refactor my code by using a BaseComponentType class and inheriting from this in my ElectricalComponentType class (and similar child classes), as follows:

BaseComponentType.java

public abstract class BaseComponentType {

    public static BaseComponentType findByUid ( Class klass, String uid ) {

        return new Select().from( klass ).where( "uid = ?", uid ).executeSingle();

    }

}

ElectricalComponentType.java

public class ElectricalComponentType extends BaseComponentType {

    public static ElectricalComponentType findByUid( String uid ) {

        return (ElectricalComponentType) findByUid( ElectricalComponentType.class, uid );

    }

}

What I need to do is call ElectricalComponentType.findByUid( 'a1234' ) but it would be great if I did not have to define findByUid in the ElectricalComponentType class and instead could inherit this functionality from the BaseComponentType.

You'll notice that two things stand in the way:

  1. I need the ElectricalComponentType class in the findByUid parent method.

  2. I need to return ElectricalComponentType object (or whatever the child class object is) instead of a BaseComponentType class object.

Is there a way to do this?

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
  • 2
    What do you mean by 'remove' the findByUid method? You can't just delete that? And your abstract class does not seem to have any abstract methods, so you don't 'have to' override anything. What is the motive here? – Praba May 03 '14 at 17:08
  • If you don't need the findByUid method in your ElectricalComponentType, then why did you program it there? I daresay the best way to remove it is never have programmed it in the first place. – Edwin Dalorzo May 03 '14 at 17:10
  • You may want to take a look here: http://stackoverflow.com/questions/10291949/are-static-methods-inherited-in-java or at any of the other ones on the right that talk about static methods and inheritance. – mttdbrd May 03 '14 at 17:15
  • By "remove", I mean that I would like to not have to **define** it in the `ElectricalComponentType` model, but I still need to do `ElectricalComponentType.findByUid( 'a433' )`. I'll update the question a little bit. – Joshua Pinter May 03 '14 at 17:17
  • @JoshPinter You're not required to override any methods except the abstract ones (which you didn't define in the sample). – mttdbrd May 03 '14 at 17:20
  • @JoshPinter Why do you want findByUid() to be static? What are you trying to accomplish? – mttdbrd May 03 '14 at 17:21
  • @mttdbrd This is essentially finding an object from the database. It makes sense to me to use `ElectricalComponentType.findByUid('a1234')` instead of `new ElectricalComponentType().findByUid('a1234')`, don't you agree? – Joshua Pinter May 03 '14 at 17:23

4 Answers4

7

Use generics and only have the parent class method:

public abstract class BaseComponentType {
    public static <T extends BaseComponentType> T findByUid(Class<T> klass, String uid) {
        return new Select().from( klass ).where( "uid = ?", uid ).executeSingle();
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • So the formatting of this is pretty special, requiring ` T`. Do you have a link I can read up on this more? – Joshua Pinter May 03 '14 at 23:31
  • 1
    Glad you like it. For more info, start with [official docs](http://docs.oracle.com/javase/tutorial/extra/generics/methods.html). If you need more google "java generic methods" or "java typed methods" – Bohemian May 04 '14 at 02:11
  • Thanks. One last thing, is it possible to determine the child class programmatically so I can remove the `Class klass` function param? – Joshua Pinter May 04 '14 at 03:10
  • 1
    If the `from()` method requires a `class` object of type `T` (which is highly likely), then "no" there is no way to avoid passing the `class` object, because due to runtime type erasure you can't create a `class` object of type `T` at runtime. – Bohemian May 04 '14 at 15:30
0

There are several points to note:

  • static methods are not being inherited and cannot be overriden;
  • To call static method of your parent class, you have to write class name first: BaseComponentType.findById();

If you want to get rid of method with the same name in child class, you may want to make it non-static or/and reconsider your classes design, because if you have two static methods with the same names in classes bound with inheritance relation, most likely there is something wrong with class design.

Alexey Malev
  • 6,408
  • 4
  • 34
  • 52
0

i hope you need something like following..

public class TestClass{
    public static void main(String args[]){
        Child c2;
        c2 = (Child) Child.findByUid(Child.class, "123");
        System.out.println(c2.getClass());
    }            
}

class Base{
    public static Base findByUid ( Class klass, String uid ) {
        System.out.println(klass);
        Child c = new Child();
            //execute your query here and expect it to return the type of object as the class by which it was called
        //your parent class method always returns the type of the child by which the method was called
        return c;

    }

}

class Child extends Base{
    /*public static Child findByUid( String uid ) {
        System.out.println(Child.class);
        return (Child) findByUid( Child.class, uid );

    }*/
}
dev2d
  • 4,245
  • 3
  • 31
  • 54
0

I think you could reengineer this so that you have a ComponentFinder class that finds Components.

public class ElectricalComponent extends Component {

     @Override
     public void method1(){
         //specific stuff
     }

}

public abstract class Component{
     public abstract void method1();
}

public class ComponentFinder{

    public static Component findByUid ( Class klass, String uid ) {

        return new Select().from( klass ).where( "uid = ?", uid ).executeSingle();

    }

}

Then you don't have to worry about the inheritance issue.

mttdbrd
  • 1,791
  • 12
  • 17