Currently i am rewriting a java project by groovy, then i came across this problem
Java:
public abstract class AbstractJavaClass {
private ConfigClass configClass;
public void go();
g/setter
}
public class JavaClass extends AbstractJavaClass {
#Override
public void go() {
do something;
}
}
the ConfigClass member was injected in xml ways
<bean id = 'configClass' class='ConfigClass'></bean>
<bean id = 'javaClass' class='JavaClass'>
<property name='configClass' ref='configClass'/>
</bean>
Groovy:
class GroovyClass extends AbstractJavaClass {
#Override
public void go() {
do something;
}
}
How should i implement the property ref in groovy class?
At last i used this method.
Groovy:
class GroovyClass extends AbstractJavaClass {
public GroovyClass() {
configClass = new ConfigClass();
configClass.setSomeAttributes();
}
#Override
public void go() {
do something;
}
}
Related
This is my structure.
public class FooInfo { ... }
public class FooAInfo extends FooInfo { ... }
public class FooBInfo extends FooInfo { ... }
public interface IFoo<T1 extends FooInfo> {
void proc(T1 fooInfo);
}
public class FooA implements IFoo<FooAInfo> {
void proc(FooAInfo fooInfo) { ... }
}
public class FooB implements IFoo<FooBInfo> {
void proc(FooBInfo fooInfo) { ... }
}
And I want to use them like
public abstract class FooUser {
protected IFoo<FooInfo> foo;
}
public class FooAUser extends FooUser {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser {
public FooBUser() {
super.foo = new FooB();
}
}
I want to initialize FooUser's foo variable in FooAUser and FooBUser child class.
But It doesn't work because new FooA() and new FooB() don't have <FooInfo>.
What should I do?
You just need to make FooUser generic:
public abstract class FooUser<T extends FooInfo> {
protected IFoo<T> foo;
}
public class FooAUser extends FooUser<FooAInfo> {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser<FooBInfo> {
public FooBUser() {
super.foo = new FooB();
}
}
Alternatively, you can use a generic wildcard (?) on your foo parameter:
public abstract class FooUser {
protected IFoo<?> foo;
}
public class FooAUser extends FooUser {
public FooAUser() {
super.foo = new FooA();
}
}
public class FooBUser extends FooUser {
public FooBUser() {
super.foo = new FooB();
}
}
(Unrelated to the question, but your proc() methods in your classes also need to be declared public.)
I would like to create an object dynamically.
I have the following structure:
1 abstract class and several classes that inherit from the abstract class
abstract public class A {..}
public class B extends A{..}
public class C extends A{..}
I have a config file where i want to add a class name, to have the ability to control which class it should be used.
# config class name
classname = B
I tried the following, but here I have the problem that I have to cast the result
and I do not know how I can do it dynamically at this point
public class TestClass {
public A instB;
public void getInstance(){
this.instB = Class.forName("B") /*here i put later the config value classname*/
.getConstructor(String.class)
.newInstance(new Object[]{"test"}); // <--- How to cast this dynamicly to a class in the config?
}
}
How can I dynamically create an instance of a class?
Just cast it to A:
instB = (A)Class....newInstance(...);
You don't need to know the exact class.
I don't see the point of why you really need to use reflection. I would suggest using a simple strategy pattern, for example:
Strategy.java
public interface Strategy {
void doWork();
}
StrategyA.java
public class StrategyA implements Strategy {
#Override
public void doWork() {
}
}
Strategy B.java
public class StrategyB implements Strategy {
#Override
public void doWork() {
}
}
Main.java
public class Main {
public static void main(String[] args) {
// read the option from a config file
String option = "B";
Strategy strategy = createStrategy(option);
// create a context with the strategy
MyContext context = new MyContext(strategy);
context.doWork();
// config has changed dynamically, change the strategy
context.useStrategy(new StrategyA());
context.doWork();
}
public static Strategy createStrategy(String strategy) {
if (strategy.equals("A")) {
return new StrategyA();
}
return new StrategyB();
}
}
MyContext.java
public class MyContext {
Strategy strategy;
public MyContext(Strategy strategy) {
this.strategy = strategy;
}
public void useStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void doWork() {
strategy.doWork();
}
}
Is it possible to define following in Java:
public interface IGenericRepo<T> {
void add();
void delete();
void attach();
}
public interface IGenericRepo<Book> {
default String bookSpecificMethod(){
return "smthn";
}
}
public class NHGenericRepo<T> implements IGenericRepo<T>{
/* implementation */
}
public class NHUnitOfWork implements UnitOfWork{
#Autowired
public void setBookRepo(NHGenericRepo<Book> bookRepo) {
this.bookRepo= bookRepo;
}
public NHGenericRepo<Book> getBookRepo() {
return bookRepo;
}
private NHGenericRepo<Book> bookRepo;
}
And to be able somewhere in code to have:
{
#Autowired
public void setNhuw(NHUnitOfWork nhuw) {
this.nhuw = nhuw;
}
private NHUnitOfWork nhuw;
/**/
{
String st = this.nhuw.getBookRepo().bookSpecificMethod();
}
}
In .net this is possible by using Extension Method with "this IGenericRepo<Book>" as a first method parameter.
The closest you can come is:
public interface IBookGenericRepo extends IGenericRepo<Book> {
void BookSpecificMethod();
}
Please help resolve an issue regarding generics. I tried many ways but it's still not working.
Problem is:
public static void main(String[] args) {
Utils.execute(new TestAction(), new TestCallBack());
}
Compiler show error:
The method execute(Action<?>, CallBack<?,Action<?>>) in the type Utils is not applicable for the arguments (ImplementClass.TestAction, ImplementClass.TestCallBack)
My classes is:
Action class:
public abstract class Action<R> {
public R getResult() {
return null;
}
}
TestAction class is:
class TestAction extends Action<String> {
#Override
public String getResult() {
return super.getResult();
}
}
Callback class is:
public interface CallBack<R, A extends Action<R>> {
public void onCall(A action);}
TestCallback class is:
class TestCallBack implements CallBack<String, TestAction> {
#Override
public void onCall(TestAction action) {
}
}
And Utils class is:
public class Utils {
public static void execute(Action<?> action, CallBack<?, Action<?>> callback) {
}
}
Thanks a lot.
The second parameter of the execute method is CallBack<?, Action<?>>, and Action there means the Action class itself, subclass of it is not allowed. What you need there is - ? extends Action<?>, which means either Action or some subclass of it.
Try changing the method signature -
public static void execute(Action<?> action, CallBack<?, ? extends Action<?>> callback) {
Note:
Generics are not co-variant. Take for example a method as follows -
static void method(List<Object> l) {}
And an invocation as follows is not allowed -
method(new ArrayList<String>());
You need to change two things,
TestCallBack should be like this -
public static class TestCallBack implements CallBack<String, Action<String>> {
#Override
public void onCall(Action<String> action) {
}
}
and, Utils should be like this -
public static class Utils {
// You need to ensure the same type, not just try and accept anything.
public static <T> void execute(Action<T> action, CallBack<?, Action<T>> callback) {
}
}
or using inner classes of a class called Question -
public abstract class Action<R> {
public R getResult() {
return null;
}
}
public class TestAction extends Action<String> {
#Override
public String getResult() {
return super.getResult();
}
}
public interface CallBack<R, A extends Action<R>> {
public void onCall(A action);
}
public class TestCallBack implements CallBack<String, TestAction> {
#Override
public void onCall(TestAction action) {
}
}
public class Utils {
public void execute(Action<?> action, CallBack<?, ? extends Action<?>> callback) {
}
}
public static void main(String[] args) {
Question question = new Question();
question.new Utils().execute(question.new TestAction(), question.new TestCallBack());
}
I have this class:
public DrawItem {
protected String getSeperator() {
return "";
}
.......
// some other methods
}
I've another class which extends DrawItem.
public DrawNumber extends DrawItem {
#Override
protected String getSeperator() {
return "-";
}
}
Now, in a generic class CombinationGenerator<E>, I'm trying to instantiate objects of DrawItem/DrawNumber. As instantiating a generic type is not possible in java (like new E(...)), I've created a Factory interface according to this answer.
public interface DrawItemFactory<E> {
E create(...);
}
Then in the CombinationGenerator<E> class,
public class CombinationGenerator<E> {
DrawItemFactory<E> factory;
public CombinationGenerator<E>(DrawItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And now the DrawNumber class implements DrawItemFactory<DrawItem> interface.
public DrawItem implements DrawItemFactory<DrawItem> {
protected String getSeperator() {
return "";
}
#Override
public DrawItem create(...) {
return new DrawItem(...);
}
.......
// some other methods
}
And I can create CombinationGenerator<DrawItem> class.
DrawItem drawItem = new DrawItem(...);
CombinationGenerator<DrawItem> generator = new CombinationGenerator<DrawItem>(drawItem);
List<DrawItem> combinations = generator.generate();
So far, everything is fine. But when I try to create a DrawNumber class like this,
public DrawNumber implements DrawItemFactory<DrawNumber> {
....
}
It gives me the following error:
The interface DrawItemFactory cannot be implemented more than once with different arguments: DrawItemFactory<DrawItem> and DrawItemFactory<DrawNumber>
I've tried this solution but I got the same error. Is there any other way to do this?
Instead of using all those factories you could do something like this:
public class CombinationGenerator<E> {
E instance;
public CombinationGenerator(Class<E> clazz) {
Constructor<?> con = clazz.getConstructor();
this.instance = (E) con.newInstance();
}
}
...
CombinationGenerator<DrawNumber> cg = new CombinationGenerator<DrawNumber>(DrawNumber.class);
According to #JB Nizet's comment, I've solved the problem by creating two separate factory classes like this:
public interface ItemFactory<E> {
E create(int[] values);
public static class DrawItemFactory implements ItemFactory<DrawItem> {
#Override
public DrawItem create(int[] values) {
return new DrawItem(values);
}
}
public static class DrawNumberFactory implements ItemFactory<DrawNumber> {
#Override
public DrawNumber create(int[] values) {
return new DrawNumber(values);
}
}
}
In the CombinationGenerator,
public class CombinationGenerator<E> {
ItemFactory<E> factory;
public CombinationGenerator<E>(ItemFactory<E> factory) {
this.factory = factory;
}
public List<E> generate() {
......
list.add(factory.create(...));
......
}
}
And instantiated CombinationGenerator like this:
DrawNumber drawNumber = new DrawNumber();
CombinationGenerator<DrawNumber> generator = new CombinationGenerator<DrawNumber>(new ItemFactory.DrawNumberFactory());
List<DrawNumber> combinations = generator.generate();