This seems like a newbish question, but the last time I worked with Java, the language didn't have generics. I have a class hierarchy (names changed to be as generalized as possible):
public abstract class AbstractBase { .... }
public class ConcreateSubA extends AbstractBase { .... }
public class ConcreateSubB extends AbstractBase { .... }
...
public class ConcreateSubZZ9PluralZAlpha extends AbstractBase { .... }
...
I'm trying to clean up some legacy code, and there's one place where a ton of repetitive duplication can all be factored out into a single routine via generics. (I'm thinking generics because when this routine is called, it needs to operate on only one of the concrete classes.)
The routine looks like
public <Thing extends AbstractBase> void someFunc()
{
another_function_call (Thing.concreteSpecialToken);
// could also be
// another_function_call (Thing.concreteSpecialToken());
// if methods are more feasible than fields
// Cannot use
// another_function_call (Thing().concreteSpecialToken());
// because creating instances of these types is a Major Operation[tm]
}
I'm leaving out about a zillion lines, but that's the important part: someFunc() is type parametric (it actually takes arguments but none of them are Things so no inference). Eventually I need to fetch a special token and this is where I'm getting fuzzy.
The tokens are huge-ass unique strings for each concrete class. They're class-based, not instance-based. The actual token value is declared as a private static final field in each subclass.
So I need to use the public methods/fields of a base class to (eventually) get to the private static field of a subclass. Obviously I can't declare an abstract static method in the base, because that makes no sense. If the data were instance-based, then this would be trivial, with a polymorphic getter in the base class, but the subclass stuff is static.
I feel like I'm missing a feature of Java generics here, but I can't use Thing.whatever() unless the whatever is something that's possible to declare in the abstract base class. I'm running up against either limitations of Java or my lack of expertise trying to bridge the gap. The one attempt I made that seemed promising also had a ton of code duplication all the way down the class hierarchy, defining abstract methods with the exact same code over and over... which is what generics are supposed to help prevent!
I'm running up against either limitations of Java or my lack of expertise trying to bridge the gap.
It's a limitation of Java, although a fairly reasonable one IMO. Basically you're still trying to use static members as if they were polymorphic, and that's not going to work - generics don't help you there.
Options:
Use reflection... but bear in mind that type erasure means you can't get at the Class for Thing unless you pass it in explicitly
If you've got an instance of Thing anyway, just make it an abstract instance member, which in each implementation happens to return the value of a static field
Create a separate type hierarchy which will use instance members
If I understand it correctly, you need the concrete class of the type parameter. The usual way of doing it is to declare your method like this: public <T extends AbstractBase> void someFunc(Class<T> clazz)
This of course means an extra parameter needs to be passed to the method and you need to use reflection to access the static fields, but given Java's type erasure it's the only way.
The moral of the story is that generics and statics don't go very well together.
A bit clunky but if someFunc took a Class<Thing> parameter you could use reflection:
public <Thing extends AbstractBase> void someFunc(Class<Thing> clz) {
// exception handling omitted
Object whatever = clz.getDeclaredMethod("whatever").invoke(null);
But you could maybe take better advantage of polymorphism by using nested classes, something like
public abstract class AbstractBase {
public static class Info {
public String getInfo() {
return "AbstractBase";
}
}
}
public class ConcreteSubA extends AbstractBase {
public static final Info INFO = new Info() {
public String getInfo() { return "ConcreteSubA"; }
}
}
and have someFunc take an AbstractBase.Info parameter.
public <Thing extends AbstractBase> someFunc(AbstractBase.Info inf) {
String info = inf.getInfo();
}
// call it as
ConcreteSubB csb = someFunc(ConcreteSubB.INFO);
The idea is that each class in the hierarchy has a singleton instance of Info holding its formerly-static data.
If you want to keep the token as it is, a private static final field, you can get it through reflection:
public <Thing extends AbstractBase> void someFunc(Class<Thing> clz)
{
try {
Field field = clz.getField("concreteSpecialToken");
field.setAccessible(true);
Object concreteSpecialToken = field.get(null);
another_function_call (concreteSpecialToken);
} catch (IllegalAccessException e) {
handle(e);
} catch (NoSuchFieldException e) {
handle(e);
}
}
At call site, you have to do someFunc(ConcreateSubZZ9PluralZAlpha.class). But I wonder if you can do that, why don't you just pass the token object as a parameter, as in someFunc(ConcreateSubZZ9PluralZAlpha.concreteSpecialToken)? Or maybe even move the method someFunc() to the token class itself.
Related
I am working on creating a java utils library and have come across a problem with generics. I have found a solution that lets the library work, but it seems like bad code practice and prone to undetected program failures. For question's sake, I've simplified the program into a minimum verifiable example.
Let's say I have an interface Invokable<E>, which is called upon to effect an E.
public interface Invokable<E> {
void invoke(E e);
}
Let's say I have another interface, InvokableFactory<E>, which creates Invokable<E>s
public interface InvokableFactory<E> {
Invokable<E> create();
}
Now let's say I have a class InvokableUser<E>, that is designed to be extended. It holds an InvokableFactory<E>, and uses it to create an Invokable<E>, which it then invokes with itself.
public class InvokableUser<E> {
private InvokableFactory<E> factory;
public InvokableUser(InvokableFactory<E> factory) {
this.factory = factory;
}
public void start() {
factory.create().invoke((E) this);
}
}
You might see that my conundrum is that I'm trying to ensure that a subclass InvokableUser, extends InvokableUser of the generic type of itself. I'm trying to ensure that an InvokableUser contains a factory that produces Invokables that can be invoked with the InvokableUser object, but still be passed an object of the type of the subclass of InvokableUser so that the Invokable can utilize methods added only by the subclass of InvokableUser.
I feel like I might not be explaining this very well, so for example, let's say there's a subclass of Invokable that needs to print out the getString method added by a subclass of InvokableUser, like this:
public class PrintingInvokable implements Invokable<PrintingInvokableUser> {
#Override
public void invoke(PrintingInvokableUser e) {
System.out.println(e.getString());
}
}
public class PrintingInvokableUser extends InvokableUser<PrintingInvokableUser> {
public PrintingInvokableUser() {
super(PrintingInvokable::new);
}
public String getString() {
return "( ͡° ͜ʖ ͡°)";
}
}
If you create a new PrintingInvokableUser() and call start() on it, it will create a new PrintingInvokable() and call invoke(this) on it, when will then print out the getString() method of the PrintingInvokableUser.
While my code does work for this, it depends on the unwritten expectation that a subclass Foo of InvokableUser will extend InvokableUser<Foo>, involves an unchecked cast which is bad (and raises a compiler warning), seems to not even make use of the generic type as I could achieve the same effect with unparametrized types, and generally seems like there has to be a better way to do this.
If someone could point me in the right direction for how to do this, I'd be appreciative. Thanks!
This seems like a newbish question, but the last time I worked with Java, the language didn't have generics. I have a class hierarchy (names changed to be as generalized as possible):
public abstract class AbstractBase { .... }
public class ConcreateSubA extends AbstractBase { .... }
public class ConcreateSubB extends AbstractBase { .... }
...
public class ConcreateSubZZ9PluralZAlpha extends AbstractBase { .... }
...
I'm trying to clean up some legacy code, and there's one place where a ton of repetitive duplication can all be factored out into a single routine via generics. (I'm thinking generics because when this routine is called, it needs to operate on only one of the concrete classes.)
The routine looks like
public <Thing extends AbstractBase> void someFunc()
{
another_function_call (Thing.concreteSpecialToken);
// could also be
// another_function_call (Thing.concreteSpecialToken());
// if methods are more feasible than fields
// Cannot use
// another_function_call (Thing().concreteSpecialToken());
// because creating instances of these types is a Major Operation[tm]
}
I'm leaving out about a zillion lines, but that's the important part: someFunc() is type parametric (it actually takes arguments but none of them are Things so no inference). Eventually I need to fetch a special token and this is where I'm getting fuzzy.
The tokens are huge-ass unique strings for each concrete class. They're class-based, not instance-based. The actual token value is declared as a private static final field in each subclass.
So I need to use the public methods/fields of a base class to (eventually) get to the private static field of a subclass. Obviously I can't declare an abstract static method in the base, because that makes no sense. If the data were instance-based, then this would be trivial, with a polymorphic getter in the base class, but the subclass stuff is static.
I feel like I'm missing a feature of Java generics here, but I can't use Thing.whatever() unless the whatever is something that's possible to declare in the abstract base class. I'm running up against either limitations of Java or my lack of expertise trying to bridge the gap. The one attempt I made that seemed promising also had a ton of code duplication all the way down the class hierarchy, defining abstract methods with the exact same code over and over... which is what generics are supposed to help prevent!
I'm running up against either limitations of Java or my lack of expertise trying to bridge the gap.
It's a limitation of Java, although a fairly reasonable one IMO. Basically you're still trying to use static members as if they were polymorphic, and that's not going to work - generics don't help you there.
Options:
Use reflection... but bear in mind that type erasure means you can't get at the Class for Thing unless you pass it in explicitly
If you've got an instance of Thing anyway, just make it an abstract instance member, which in each implementation happens to return the value of a static field
Create a separate type hierarchy which will use instance members
If I understand it correctly, you need the concrete class of the type parameter. The usual way of doing it is to declare your method like this: public <T extends AbstractBase> void someFunc(Class<T> clazz)
This of course means an extra parameter needs to be passed to the method and you need to use reflection to access the static fields, but given Java's type erasure it's the only way.
The moral of the story is that generics and statics don't go very well together.
A bit clunky but if someFunc took a Class<Thing> parameter you could use reflection:
public <Thing extends AbstractBase> void someFunc(Class<Thing> clz) {
// exception handling omitted
Object whatever = clz.getDeclaredMethod("whatever").invoke(null);
But you could maybe take better advantage of polymorphism by using nested classes, something like
public abstract class AbstractBase {
public static class Info {
public String getInfo() {
return "AbstractBase";
}
}
}
public class ConcreteSubA extends AbstractBase {
public static final Info INFO = new Info() {
public String getInfo() { return "ConcreteSubA"; }
}
}
and have someFunc take an AbstractBase.Info parameter.
public <Thing extends AbstractBase> someFunc(AbstractBase.Info inf) {
String info = inf.getInfo();
}
// call it as
ConcreteSubB csb = someFunc(ConcreteSubB.INFO);
The idea is that each class in the hierarchy has a singleton instance of Info holding its formerly-static data.
If you want to keep the token as it is, a private static final field, you can get it through reflection:
public <Thing extends AbstractBase> void someFunc(Class<Thing> clz)
{
try {
Field field = clz.getField("concreteSpecialToken");
field.setAccessible(true);
Object concreteSpecialToken = field.get(null);
another_function_call (concreteSpecialToken);
} catch (IllegalAccessException e) {
handle(e);
} catch (NoSuchFieldException e) {
handle(e);
}
}
At call site, you have to do someFunc(ConcreateSubZZ9PluralZAlpha.class). But I wonder if you can do that, why don't you just pass the token object as a parameter, as in someFunc(ConcreateSubZZ9PluralZAlpha.concreteSpecialToken)? Or maybe even move the method someFunc() to the token class itself.
I have a series of classes, A,B,C... (several dozen in total) that share common code. There can be many instance of each class A,B,C... . I'm planning to create a superclass, Abstract, that will contain that code instead.
Problem is, the common stuff works on an object that is unique on a per-class (not per-instance) basis. This is currently solved by A,B,C... each having a static field with the corresponding value. Obviously, when I refactor the functionality into Abstract, this needs to be changed into something else.
In practice, it currently looks like this (note that the actual type is not String, this is just for demonstrative purposes) :
public class A implements CommonInterface {
private static final String specificVar = "A";
#Override
public void common() {
specificVar.contains('');
}
}
public class B implements CommonInterface {
private static final String specificVar = "B";
#Override
public void common() {
specificVar.contains('');
}
}
The best idea I've come up with until now is to have a Map<Class<? extends Abstract>,K> (where K is the relevant type) static field in Abstract, and A,B,C... each containing a static initalization block that places the relevant value into the map. However, I'm not convinced this is the best that can be done.
Note that I'm not using any DI framework.
So, what would be the most concise, in terms of code contained in the subclasses, way to refactor the static fields in A,B,C... handled by the common code, without sacrificing field access efficiency?
Perhaps an enum is what you want.
enum MyInstances implements MyInterface {
A {
fields and methods for A
}, B {
fields and methods for B
};
common fields for all MyInstances
common methods for all MyInstances
}
// To lookup an instance
MyInstances mi = MyInstances.valueOf("A");
As you haven't shown any source code, we can't really tell if the use of static fields is a good or a bad design choice.
Considering the use of static fields by the subclasses is indeed a good design choice, the first way of having common code in a superclass to access them is by calling abstract methods that would be implemented in the subclasses.
Example:
public abstract class SuperClass {
public void processCommonLogic() {
// Common logic
// Execute specific logic in subclasses
processSpecificLogic();
}
public abstract void processCommonLogic();
}
public class ASubClass extends SuperClass {
public static int SPECIFIC_SUBCLASS_CONSTANT = 0;
public void processSpecificLogic() {
// Specific subclass logic
doSomethingWith(ASubClass.SPECIFIC_SUBCLASS_CONSTANT);
}
}
You could use the Template Method Pattern.
Have an abstract method getValue() defined in your abstract class and used within your abstract class wherever you require the value. Then each of your subclasses simply need to implement the getValue method and return the correct value for that subclass.
First things first, please be aware I am trying to express my question as best I can with my current knowledge and vocabulary, so please excuse this...
I have an abstract class in which I want to make a method where it instantiates itself.... Of course this is impossible in an abstract class, however, what I really want is for the concrete children (those classes that "extends") to inherit this instantiation so that they then can instantiate themselves....
Basically what I want to do is this:
MyAbstract a = new this();
However this isn't allowed... Is there any way I can do what I want?
Here is some non-compiling dream-code (i.e. code I wish worked). Basically I am wanting the ConcreteChild to call a method in which it create an object of itself. The method is inherited from it's parent.
public class Abstract {
public void instantiateMyConcreteChild()
{
Abstract a = new this();
}
}
public class ConcreteChild extends Abstract{
public static void main(String[] args) {
ConcreteChild c = new ConcreteChild();
c.instantiateMyConcreteChild();
}
}
* Additional info **
Thanks for the replies but I think I missed something vital....
Basically I wanted to pass an object's self ( "this" ) into some methods of some other classes. However, creating instantiating another object within an object is a bit backwards, I can just pass "this", right...
You can do this using reflection, something like :
Abstract a = getClass().newInstance();
This is because getClass() always returns the concrete class, so this.getClass() will return the real subclass and not the current class.
However, beware that if the subclass defines a custom constructor, having more or less parameters than your abstract class, it could fail. Unless you specify in the documentation that subclasses must have a constructor with such given parameters ... but it's fragile anyway.
You can inspect it, using getClass().getConstructors() and see which constructors are there, and if there is the one you are expecting, or even search for a viable one, otherwise you can catch the exception thrown by newInstance(..), and wrap it in a more descriptive exception for the users, so that they understand better what they missed ... but it would still be a kind of a hack, cause there is no explicit language support for such a situation.
Another approach could be to implement Cloneable in your abstract class, and then use the clone method, but it could be overkill or even wrong if what you want is a new, clean instance.
You can't do this using an instance method. Because as the name implies an instance methods requires that the instance has already instantiated.
What you actually need to do here is to separate the non-changing internal functionality from the abstract class itself. So what I could do is to ,for e.g., have an inner class that really encapsulates the non-changing functionality like so:
public class Abstract {
public void instantiateMyConcreteChild()
{
Abstract a = new NonChangingOperations();
}
class NonChangingOperations
{
public void operationA() {}
}
}
Infact you really dont need to keep the class NonChangingOperations as an inner class, you could make it as an external utility class with its own class hierarchy.
Are you trying to define a constructor that the subclasses of Abstract can use? If so you could simply do it the same way you define any other constructor.
public class Abstract {
Abstract() {
//set fields, etc. whatever you need to do
}
}
public class ConcreteChild extends Abstract{
ConcreteChild() {
//call superclass's constructor
super();
}
}
Could you just have this ?
public abstract class AbstractClassWithConstructor {
public AbstractClassWithConstructor() {
init();
}
protected abstract void init();
}
FYI
In the objective-c you need to set this by calling method init. The the method init() would look like this:
protected AbstractClassWithConstructor init() {
return this;
}
This isn't exactly the definition of implicit type conversion, but I'm curious how many standards I'm breaking with this one...
I'm creating an abstract class in Java that basically casts its variables depending on a string passed into the constructor.
For example:
public abstract class MyClass {
Object that;
public MyClass(String input){
if("test1".equals(input){
that = new Test1();
}
else{
that = new Test();
}
}
public void doSomething(){
if(that instanceof Test1){
//specific test1 method or variable
} else if(that instanceof Test2)}
//specific test2 method or variable
} else {
//something horrible happened
}
}
}
You see what I'm getting at? Now the problem I run into is that my compiler wants me to explicitly cast that into Test1 or Test2 in the doSomething method - which I understand, as the compiler won't assume that it's a certain object type even though the if statements pretty much guarantee the type.
I guess what I'm getting at is, is this a valid solution?
I have other classes that all basically do the same thing but use two different libraries depending on a simple difference and figure this class can help me easily track and make changes to all of those other objects.
You are right. This is a horrible way to achieve polymorphism in design. Have you considered using a factory? A strategy object? It sounds like what you are trying to achieve can be implemented in a more loosely-coupled way using a combination of these patterns (and perhaps others).
For the polymorphism of doSomething, for example:
interface Thing {
public void doThing();
}
class Test1 implements Thing {
public void doThing() {
// specific Test1 behavior
}
}
class Test2 implements Thing {
public void doThing() {
// specific Test2 behavior
}
}
class MyClass {
Thing _thing;
public void doSomething() {
_thing.doThing(); // a proper polymorphism will take care of the dispatch,
// effectively eliminating usage of `instanceof`
}
}
Of course, you need to unify the behaviors of Test1 and Test2 (and other concrete Thing classes, present and planned) under a set of common interface(s).
PS: This design is commonly known as Strategy Pattern.
I would create a separate class file. So you would have something like this:
1. You abstract "MyClass"
->within "MyClass" define an abstract method call doSomething...this will force the specific implementation of the method to it's subclasses.
2. Test1 would be the implementation of MyClass which would contain the implementation of the doSomething method
3. Create a utility class that does the check "instanceOf" that check should not be in the constructor it belongs in another class.
So in the end you would have 3 class files an Abstract Class, Implementation of the Abstract and a Class that does the "instanceOf" check. I know this sounds like a lot but it's the proper way to design, for what I think you are attempting to do. You should pick up a design patterns book, I think it would help you a lot with questions like these.
The Open-Closed principle would be better satisfied by moving the object creation outside of this class.
Consider changing the constructor to accept an object that implements an interface.
public MyClass {
public MyClass( ITest tester ) { m_tester = tester; }
public void doSomething(){ m_tester.doTest(); }
}
This makes it possible to change the behavior of the class (open to extension) without modifying its code (closed to modification).
The better way to do this is to create an interface which will specify a set of methods that can be guaranteed to be called on the object.
Here's an example:
public interface TestInterface
{
void doTest();
}
Now you can write your classes to implement this interface. This means that you need to provide a full definition for all methods in the interface, in this case doTest().
public class Test implements TestInterface
{
public void doTest()
{
// do Test-specific stuff
}
}
public class Test1 implements TestInterface
{
public void doTest()
{
// do Test1-specific stuff
}
}
Looks really boring and pointless, right? Lots of extra work, I hear you say.
The true value comes in the calling code...
public abstract class MyObject
{
Test that;
// [...]
public void doSomething()
{
that.doTest();
}
}
No if statements, no instanceof, no ugly blocks, nothing. That's all moved to the class definitions, in the common interface method(s) (again, here that is doTest()).