I'm trying to solve this "composition + generics" situation, and make PostCompany.send(msg) be compatible with the type passed/injected to the class.
What could I change to allow both Fedex and FedexPlus being used as generic Types at PostCompany class, since Fexed's send method expects String as parameter and FeexPlus expects Integer?
interface Poster<T> {
void send(T msg);
}
class Fedex implements Poster<String> {
#Override
public void send(String msg) {
// do something
}
}
class FedexPlus implements Poster<Integer> {
#Override
public void send(Integer msg) {
// do something
}
}
class PostCompany<P extends Poster> {
private final P poster;
public PostCompany(P poster) {
this.poster = poster;
}
public void send(??? msg) { // <-- Here
this.poster.send(msg);
}
}
You missed the type of a Poster
class PostCompany<T, P extends Poster<T>> {
public void send(T msg) { // <-- Here
this.poster.send(msg);
}
}
But it actually better to just type the type of the object
class PostCompany<T> {
private final Poster<T> poster;
public PostCompany(Poster<T> poster) {
this.poster = poster;
}
public void send(T msg) { // <-- Here
this.poster.send(msg);
}
}
Since you will always be using the interface methods of Poster
You are using the raw form of Poster when defining PostCompany. You need to define another type parameter to capture the type argument for Poster.
Then you can use that new type parameter as the type argument to Poster and as the parameter type to the send method.
class PostCompany<T, P extends Poster<T>> {
and
public void send(T msg) {
Related
I need to receive some data via JSON, and I'm using Volley, with a Callback.
Data could be a simple string or a JSONArray.
Is it possibile to rewrite in only one generic method?
public interface BaseMapper {
final static String API_URL_LOGIN = "/apiv2/account";
final static String API_URL_CAMPAIGN = "/apiv2/campaign";
final static String API_URL_SEARCH_CARD ="/apiv2/member-card?card=";
public interface VolleyCallbackArray {
void onSuccess(JSONArray array);
}
public interface VolleyCallbackString {
void onSuccess(String string);
}
}
VolleyCallbackArray and VolleyCallbackString could be replaced by a single generic:
public interface VolleyCallback<T> {
void onSuccess(T result);
}
Then you specify T at time of implementing:
public class A implements BaseMapper.VolleyCallback<JSONArray> {
public void onSuccess(JSONArray result){
}
}
public class B implements BaseMapper.VolleyCallback<String> {
public void onSuccess(String result){
}
}
I'm developing a database application for android devices.
First thing I need to do is creating the data access layer.
For this I want to use DAO-Pattern with abstract factories.
For all DAOs i have one Interface witch contains the declaration that all data object needs to implement. (in my case: IDataObject)
The specific DAOs are all represented by its own interface, extending the base interface of all DAOs.
base interface:
public interface IDataObject {
public IDataId getId();
public void write() throws MyDataWriteException;
public void validate() throws MyDataValidException;
}
a extensions:
public interface IDataSample1 extends IDataObject {
public void setNotice(String notice);
public String getNotice();
public void setDate(Date date);
public Date getDate();
}
To create an data object I want use abstract to use abstract factories, something like:
public interface IDataFactory<Template extends IDataObject> {
public List<Template> getAll();
public Template get(IDataId id);
public List<Template> getList(DataAccessArgument arg);
public List<Template> getList(List<DataAccessArgument> argList);
}
and the implementation:
public class DataSample1Fac implements IDataFactory<IDataSample1> {
public DataSample1Fac () {
}
public List<IDataSample1> getAll() {
return null;
}
public IDataSample1 get(IDataId id) {
return null;
}
public List<IDataSample1> getList(DataAccessArgument arg) {
return null;
}
public List<IDataSample1> getList(List<DataAccessArgument> argList) {
return null;
}
}
I don't get any error so far, but now I want to implement an factory builder:
public class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static<T extends IDataObject> IDataFactory<T> getFactory(){
if (T instanceof IDataSample1)
return new DataSample1Fac();
return null;
}
}
I get following errors(line 8):
T cannot be resolved to a variable
and (line 9)
Type mismatch: cannot convert from DataSample1Fac to IDataFactory<T>
Don't know how to fix this, any suggestions?
I would refactor Your's DataFactoryBuilder to something like that:
class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static IDataFactory<? extends IDataObject> getFactory(Class<? extends IDataObject> clazz){
if (IDataSample1.class.isAssignableFrom(clazz)) {
return new DataSample1Fac();
}
return null;
}
}
I got following solution:
public static <T extends IDataObject> IDataFactory<T> getFactory(Class<T> type) {
if (IDataSample1.class.isAssignableFrom(type)) {
DataSample1Facfac = new DataSample1Fac();
return (IDataFactory<T>) fac;
}
}
but i get an warning on: return (IDataFactory) fac;
Type safety: Unchecked cast from DataSample1Fac to IDataFactory<T>
I think that is not a problem, I just have to supress it
I have a requirement that is close to extending enums and since that is not possible, after doing some research online, I came up with this approach of using interfaces and making the enums extend them.
My problem is that I have a few basic types A,B and a flag for each type that says if that has to be checked. Similarly I have some extended types C... which do the same stuff after checking their flags.
Here is the code that does this
Type Interface:
public interface Type {
public String name();
}
Here is the class that uses the basic types
public class BasicChecker {
private static boolean checkA = false;
private static boolean checkB = false;
public enum BasicType implements Type {
A, B;
}
public static boolean isCheckA() {
return checkA;
}
public static void setCheckA(boolean checkA) {
BasicChecker.checkA = checkA;
}
public static boolean isCheckB() {
return checkB;
}
public static void setCheckB(boolean checkB) {
BasicChecker.checkB = checkB;
}
public static void doStuff(String message, Type type) {
if (type.name().equalsIgnoreCase(BasicType.A.name())) {
doStuff(message, isCheckA());
} else if (type.name().equalsIgnoreCase(BasicType.B.name())) {
doStuff(message, isCheckB());
}
}
protected static void doStuff(String message, boolean flag) {
if (someCheckMethod() && flag) {
doStuff(message, flag);
}
}
private static boolean someCheckMethod() {
return false;
}
}
And this is the class that uses extended types
public class ExtendedChecker extends BasicChecker {
private static boolean checkC = false;
public enum ExtendedType implements Type {
C;
}
public static boolean isCheckC() {
return checkC;
}
public static void setCheckC(boolean checkC) {
ExtendedChecker.checkC = checkC;
}
public static void doStuff(String message, Type type) {
BasicChecker.doStuff(message, type);
if (type.name().equalsIgnoreCase(ExtendedType.C.name())) {
doStuff(message, isCheckC());
}
}
}
What I am trying to solve now is to remove all the if else cases from log method. I am also trying to see if there is a better way to do this. Please ignore the statics. I do want them to be static fields and methods.
I'm having trouble understanding exactly what you're trying to do from your description, but you may find abstract methods in enums to be useful.
For example, you could add an abstract method "foo" to your enums:
public enum BasicType implements Type {
A {
public void foo(String message) {
// Do special A stuff
}
}, B {
public void foo(String message) {
// Do special B stuff
}
};
public abstract void foo(String message);
}
And you could then use that method like this:
public static void doStuff(String message, Type type) {
type.foo(message);
}
Naturally, you could put any such abstract methods in an interface you extend, if that's useful.
public class BasicChecker {
private static final Set<Type> _doCheck = Collections.newSetFromMap(new ConcurrentHashMap<Type,Boolean>());
public enum BasicType implements Type {
A, B;
}
public static boolean isCheck(Type type) {
return return _doCheck.contains(type);
}
public static void setCheck(Type type, boolean check) {
if(check) {
_doCheck.add(type);
} else {
_doCheck.remove(type);
}
}
public static void doStuff(String message, Type type) {
doStuff(message, isCheck(type));
}
}
I asked before for an example "annotation processor" that would generate a Proxy/Delegate for an interface, but got no answer, and did not find anything on the Internet, so I made my own.
So far it worked well, until I tried to use generics inside a super-interface. If I use generics in the annotated interface, it works fine (more by accident than by design). But if the annotated interface extends another interface that takes a generic type parameter, that parameter is not "bound" to the type that the annotated interface use when extending the super-interface. Example:
public interface TestFragment<E> {
void test(E dummy);
}
#CreateWrapper
public interface TestService extends TestFragment<String> {
double myOwnMethod();
}
This would generate:
// ...
public void test(final E dummy) {
wrapped.test(dummy);
}
// ...
instead of the correct:
// ...
public void test(final String dummy) {
wrapped.test(dummy);
}
// ...
The code that generates the parameters in the generated methods look like this:
int count = 0;
for (VariableElement param : method.getParameters()) {
if (count > 0) {
pw.print(", ");
}
count++;
pw.printf("final %s %s", param.asType().toString(),
param.getSimpleName().toString());
}
Is there a way to do this?
Have a look at http://docs.oracle.com/javase/6/docs/api/javax/lang/model/util/Types.html#asMemberOf%28javax.lang.model.type.DeclaredType,%20javax.lang.model.element.Element%29
Might be helpful. I used it to solve a very similar problem.
This can be quite simple if you follow Ryan Walls suggestion of using asMemberOf
ExecutableType methodType = (ExecutableType) typeUtil
.asMemberOf((DeclaredType) theAnnotatedClass.asType(), method);
int count = 0;
for (VariableElement param : method.getParameters()) {
if (count > 0) {
pw.print(", ");
}
TypeMirror actualParamType = methodType.getParameterTypes().get(count);
pw.printf("final %s %s", actualParamType.toString(),
param.getSimpleName().toString());
count++;
}
What you need is substitution, given a map of type variables to type arguments. In this case, E->String. Replace any E in any type with String
There is no such support in javax.lang.model.util.Types, you need to roll your own. Basically
void print(TypeMirror type, Map<TypeVariable,TypeMirror> substitution)
if(substitution.containsKey(type)) // type is a var, E
print( substitution.get(type) ); // String
else if(type instanceof DeclaredType) // e.g. List<E>
print( type.asElement().getSimpleName() ); // List
for(TypeMirror arg : type.getTypeArguments() ) // E
print(arg, substitution)
etc. something like that
Copy-paste of my original answer:
This seems to be a common question so, for those arriving from Google: there is hope.
The Dagger DI project is licensed under the Apache 2.0 License and contains some utility methods for working with types in an annotation processor.
In particular, the Util class can be viewed in full on GitHub (Util.java) and defines a method public static String typeToString(TypeMirror type). It uses a TypeVisitor and some recursive calls to build up a string representation of a type. Here is a snippet for reference:
public static void typeToString(final TypeMirror type, final StringBuilder result, final char innerClassSeparator)
{
type.accept(new SimpleTypeVisitor6<Void, Void>()
{
#Override
public Void visitDeclared(DeclaredType declaredType, Void v)
{
TypeElement typeElement = (TypeElement) declaredType.asElement();
rawTypeToString(result, typeElement, innerClassSeparator);
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (!typeArguments.isEmpty())
{
result.append("<");
for (int i = 0; i < typeArguments.size(); i++)
{
if (i != 0)
{
result.append(", ");
}
// NOTE: Recursively resolve the types
typeToString(typeArguments.get(i), result, innerClassSeparator);
}
result.append(">");
}
return null;
}
#Override
public Void visitPrimitive(PrimitiveType primitiveType, Void v) { ... }
#Override
public Void visitArray(ArrayType arrayType, Void v) { ... }
#Override
public Void visitTypeVariable(TypeVariable typeVariable, Void v)
{
result.append(typeVariable.asElement().getSimpleName());
return null;
}
#Override
public Void visitError(ErrorType errorType, Void v) { ... }
#Override
protected Void defaultAction(TypeMirror typeMirror, Void v) { ... }
}, null);
}
I am busy with my own project which generates class extensions. The Dagger method works for complex situations, including generic inner classes. I have the following results:
My test class with field to extend:
public class AnnotationTest
{
...
public static class A
{
#MyAnnotation
private Set<B<Integer>> _bs;
}
public static class B<T>
{
private T _value;
}
}
Calling the Dagger method on the Element the processor provides for the _bs field:
accessor.type = DaggerUtils.typeToString(element.asType());
The generated source (custom, of course). Note the awesome nested generic types.
public java.util.Set<AnnotationTest.B<java.lang.Integer>> AnnotationTest.A.getBsGenerated()
{
return this._bs;
}
EDIT: adapting the concept to extract a TypeMirror of the first generic argument, null otherwise:
public static TypeMirror getGenericType(final TypeMirror type)
{
final TypeMirror[] result = { null };
type.accept(new SimpleTypeVisitor6<Void, Void>()
{
#Override
public Void visitDeclared(DeclaredType declaredType, Void v)
{
List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
if (!typeArguments.isEmpty())
{
result[0] = typeArguments.get(0);
}
return null;
}
#Override
public Void visitPrimitive(PrimitiveType primitiveType, Void v)
{
return null;
}
#Override
public Void visitArray(ArrayType arrayType, Void v)
{
return null;
}
#Override
public Void visitTypeVariable(TypeVariable typeVariable, Void v)
{
return null;
}
#Override
public Void visitError(ErrorType errorType, Void v)
{
return null;
}
#Override
protected Void defaultAction(TypeMirror typeMirror, Void v)
{
throw new UnsupportedOperationException();
}
}, null);
return result[0];
}
I would like to know how to create a contract with the caller for the Method parameter in the event the method has parameters itself. So that I use...
ClassA {
String string_ = "HI";
public static void subscribe(Object class, Method action) {
action.invoke(class, string_);
}
}
ClassB {
ClassB() {
ClassA.subscribe(this, this.getClass().getMethod("load", String.class));
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
I would like to know how to ensure the Method passed as "action" takes String as a parameter (i.e. ensure Method action == load(String){})? Is there something like this available:
public static void subscribe(Object class, Method action(String.class)) {
I want to do it in the method signature of subscribe so that it is obvious to the calling class (ClassB) that it needs to be prepared to take an argument of specified type.
EDIT: Updated last code bit so not to appear as if Method was generic. Poor choice of using <> on my part to represent an example of what I was trying to convey.
There's no way to do that in Java. The Method class is not generic, and there is no way for it to be so, because methods can take any number of parameters, and there is no way to make a class generic over a variable number of types.
Probably the best you can do is to declare your own type to use instead of Method:
public interface Action<T, P> {
public void invoke(T target, P parameter);
}
Then:
public static <T> void subscribe(T obj, Action<T, String> action) {
action.invoke(obj, string_);
}
ClassB() {
ClassA.subscribe(this, new Action<ClassB, String>() {
public void invoke(ClassB target, String parameter) {
target.load(parameter);
}
});
}
In C# there are means to achieve what you are trying to do but I can't think of a way to ensure that at compile time for java.
can you resort to using intefaces?
interface ILoader{
void load(String input);
}
ClassA {
String string_ = "HI";
public static void subscribe(ILoader loader) {
loader.load( string_);
}
}
ClassB implements ILoader {
ClassB() {
ClassA.subscribe(this);
}
public void load(String input) {
if(input.equals("HI")) {
...
}
}
}
Couldn't you use a slight modification of the Command Pattern?
puclic interface LoadCommand {
public load(String input);
}
public class ClassB implements LoadCommand {
public load(String input) {
// do stuff here
}
}
public class ClassA {
String myInput = "HI";
public static void subscribe(LoadCommand command) {
command.load(myInput)
}
}
The load method in the LoadCommand interface takes one String argument.