method based on variable type - class

I just have the following scenario
i want to return string from method but the method should be based on variable type which is (Type CType)
i need to make the render class like this
public string render(TextBox ctype){
return "its text box";
}
public string render(DropDown ctype){
return "its drop down";
}
you know TextBox is a Type thats why i can declare the Type variable like this
var CType = typeof(TextBox)
and i need to call the render method like this
render(Ctype);
so if the Ctype is type of TextBox it should call the render(TextBox ctype)
and so on
How can i make it ?

you should use a template function
public customRender<T>(T ctype)
{
if(ctype is TextBox){
//render textbox
}
else if(ctype is DropDown){
//render dropdown
}
}
hope it will help

First of all, even if you don't see an if or a switch, there will still be one somewhere hidden inside some functions. Distinguishing types at runtime that are not known at compile-time simply will not be possible without any such kind of branching of the control flow.
You can use one of the collection classes to build a map at runtime that maps Type instances to Func<T, TResult> methods. For example, you can use the Dictionary type to create such a map:
var rendererFuncs = new Dictionary<Type, Func<object, string>>();
You could then add some entries to that dictionary like this:
rendererFuncs[typeof(TextBox)] = ctype => "its text box";
rendererFuncs[typeof(DropDown)] = ctype => "its drop down";
Later on, you can call the appropriate function like this:
string renderedValue = rendererFuncs[Ctype.GetType()](Ctype);
Or, if you want to be on the safe side (in case there are Ctype values that have no appropriate renderer):
string renderedValue;
Func<object, string> renderer;
if (rendererFuncs.TryGetValue(Ctype.GetType(), out renderer)) {
renderedValue = renderer(Ctype);
} else {
renderedValue = "(no renderer found)";
}
Note that this will only work for as long as Ctype is of the exact type used as a key in the dictionary; if you want any subtypes to be correctly recognized as well, drop the dictionary and build your own map that traverses the inheritance hierarchy of the type being searched (by using the Type.BaseType property).

Related

Why Class.java don't provide methods like `Type getType()` and `Type getGenericType()`?

Why I have to define a subclass to get the Type of superclass' generic param? Is the limit necessary?
I read the code of Fastjson of Alibaba and tried to figure out why use TypeReference must create an anonymous subclass. Then I found that an object cannot get its own generic param Type even its own Type.
public class TypeReference {
static ConcurrentMap<Type, Type> classTypeCache
= new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);
protected final Type type;
protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type cachedType = classTypeCache.get(type);
if (cachedType == null) {
classTypeCache.putIfAbsent(type, type);
cachedType = classTypeCache.get(type);
}
this.type = cachedType;
}
// ...
}
Sorry for my poor English. Thanks for your answers.
Because of Type Erasure.
Consider the following example
List<String> stringList = new ArrayList<>();
List<Number> numberList = new ArrayList<>();
System.out.println(stringList.getClass() == numberList.getClass());
This will print true. Regardless of the generic type, both instances of ArrayList have the same class and a single Class object. So how could this single Class object return the right Type for both objects?
We can even get a step further,
List<String> stringList = Collections.emptyList();
List<Number> numberList = Collections.emptyList();
System.out.println(stringList == (Object)numberList);
Objects do not know their generic type. If a collection is immutable and always empty, it can be used to represent arbitrary empty lists. The same applies to stateless functions
Function<String, String> stringFunction = Function.identity();
Function<Number, Number> numberFunction = Function.identity();
System.out.println(stringFunction == (Object)numberFunction);
Prints true (on most systems; this is not a guaranteed behavior).
Generic types are only retained in some specific cases, like the signatures of field and method declarations and generic super types.
That’s why you need to create a subclass to exploit the fact that it will store the declared generic supertype. While it sometimes would be useful to construct a Type instance in a simpler way and a suitable factory method can be regarded a missing feature, getting the actual generic type of an arbitrary object (or its Class) is not possible in general.

A way to read a String as dart code inside flutter?

I want to build a method to dynamically save attributes on a specific object
given the attribute name and the value to save I call the "save()" function to update the global targetObj
var targetObj = targetClass();
save(String attribute, String value){
targetObj.attribute = value;
print(targetObj.attribute);
}
But I'm getting the following error:
Class 'targetClass' has no instance setter 'attribute='.
Receiver: Instance of 'targetClass'
Tried calling: attribute="Foo"
The only thing that I can think of is that "attribute" due to being type String results in an error.
That lead me to think if there is a way to read a String as code, something like eval for php.
As #Randal mentioned, you cannot create class..method at runtime. Still, you can try something like this.
A certain class
class Foo {
dynamic bar1;
dynamic bar2;
// ...
}
Your save method
save(Foo fooObject, String attribute, dynamic value) {
if ("bar1" == attribute) fooObject.bar1 = value;
else if ("bar2" == attribute) fooObject.bar2 == value;
// ...
}
Dart (and thus flutter) does not have a way to compile and execute code at runtime (other than dart:mirrors, which is deprecated). You can build additional code that derives from other code using the various builder mechanisms, although it can be rather complicated to implement (and use!).

Using Class<T> as a Map key in Haxe

I'd like to store instances of models in a common provider using their classes or interfaces as a keys and then pop them up by class references. I have written some code:
class Provider {
public function new() { }
public function set<T:Any>(instance:T, ?type:Class<T>) {
if (type == null)
type = Type.getClass(instance);
if (type != null && instance != null)
map.set(type, instance);
}
public function get<T:Any>(type:Class<T>):Null<T> {
return cast map.get(type);
}
var map = new Map<Class<Any>, Any>();
}
...alas, it's even doesn't compile.
Probably I have to use qualified class name as a key rather than class/interface reference? But I'd like to keep neat get function design that takes type as argument and returns object just of type taken, without additional type casting.
Is it possible or should I change my approach to this problem?
The issue of using Class<T> as a Map key come up every so often, here is a related discussion. The naive approach of Map<Class<T>, T> fails to compile with something like this:
Abstract haxe.ds.Map has no #:to function that accepts haxe.IMap<Class<Main.T>, Main.T>`
There's several different approaches to this problem:
One can use Type reflection to obtain the fully qualified name of a class instance, and then use that as a key in a Map<String, T>:
var map = new Map<String, Any>();
var name = Type.getClassName(Main);
map[name] = value;
For convenience, you would probably want to have a wrapper that does this for you, such as this ClassMap implementation.
A simpler solution is to simply "trick" Haxe into compiling it by using an empty structure type ({}) as the key type. This causes ObjectMap to be chosen as the underlying map implementation.
var map = new Map<{}, Any>();
map[Main] = value;
However, that allows you to use things as keys that are not of type Class<T>, such as:
map[{foo: "bar"}] = value;
The type safety issues of the previous approach can be remedied by using this ClassKey abstract:
#:coreType abstract ClassKey from Class<Dynamic> to {} {}
This still uses ObjectMap as the underlying map implementation due to the to {} implicit cast. However, using a structure as a key now fails at compile time:
var map = new Map<ClassKey, Any>();
map[{foo: "bar"}] = value; // No #:arrayAccess function accepts arguments [...]

Eclipse JDT static field modifiers

I want to get the information about a field modifier. To be precise, I want to find out is the field a static one. For example, I want to examine the following code:
ASTParser parser = ASTParser.newParser(AST.JLS3);
How can I infer that the JLS3 is static field? I used getModifiers with Modifier.isStatic when analyzing methods and it worked fine. However, now I am not able to get the information that JLS3 in above code snippet is a static field. Is there something I am missing?
EDIT:
This is the code that I am using:
private boolean visit(SimpleName name){
boolean isStatic = Modifier.isStatic(name.resolveTypeBinding().getModifiers());
...
return true;
}
isStatic is false in the case of JLS3.
That's obviously wrong, use name.resolveBinding() instead of name.resolveTypeBinding() --- so you should get an object of type IVariableBinding.
name.resolveTypeBinding() returns the binding for the type of the field, but not the binding of field itself, which is not what you want here.

Get type of class field with null value in Haxe

Is it possible to get class of field with null value in haxe?
The function "Type.getClass" gets class of value (setted at runtime), but I need to get class defined in a compilation-time.
Function "getClassFields" returns only names of fields, without classes.
For example:
class MyCls
{
public static var i:Int = null;
public static var s:String = null;
}
trace(Type.getClass(MyCls.i)); // show "null", but I need to get Int
trace(Type.getClass(MyCls.s)); // show "null", but I need to get String
And in my situation I can't to change sources of class MyCls.
Thanks.
You can try Runtime Type Information. It's a Haxe feature which allow go get full description of a type in runtime.
http://haxe.org/manual/cr-rtti.html
Since you need to get the types for null fields, you really need to resort to Haxe's Runtime Type Information (RTTI) (as #ReallylUniqueName recomended).
import haxe.rtti.Rtti;
import haxe.rtti.CType;
class Test {
static function main()
{
if (!Rtti.hasRtti(MyCls))
throw "Please add #:rtti to class";
var rtti = Rtti.getRtti(MyCls);
for (sf in rtti.statics)
trace(sf.name, sf.type, CTypeTools.toString(sf.type));
}
}
Now, obviously, there's a catch...
RTTI requires a #:rtti metadata, but you said you cannot change the MyCls class to add it. The solution then is do add it through a macro in your build file. For instance, if you're using a .hxml file, it should then look like:
--interp
--macro addMetadata("#:rtti", "MyCls")
-main Test
With this and your own MyCls definition, the output would look like:
Test.hx:11: i,CAbstract(Int,{ length => 0 }),Int
Test.hx:11: s,CClass(String,{ length => 0 }),String