I'm stuck with this problem for several hours. I'm trying to find an equivalent method for C#.
Java, works:
public class Main
{
public static void main(String[] args)
{
ArrayList<BaseList<? extends Base>> list = new ArrayList<>();
list.add(new DerivedList());
}
}
public class BaseList<T extends Base>
{
}
public class Base
{
}
public class DerivedList extends BaseList<Derived>
{
}
public class Derived extends Base
{
}
I need an equivalent method for ArrayList<BaseList<? extends Base>> in C#. I hope someone help me.
And is it posible in C# to wildcard your variables??
You cannot do that exactly as you describe, but there are workarounds. One is mentioned in another answer, another is to use interface instead:
public class Main
{
public static void main(String[] args)
{
var list = new List<IBaseList<Base>>();
list.Add(new DerivedList());
}
}
// note "out" here
public interface IBaseList<out T> where T : Base {
}
public class BaseList<T> : IBaseList<T> where T : Base {
}
public class Base {
}
public class DerivedList : IBaseList<Derived> {
}
public class Derived : Base {
}
C# uses runtime type reification, whereas Java uses type erasure. Which means that in Java, ArrayList<Foo> is the same class as ArrayList<Bar> at runtime. This is not the case in C#, so you can't just throw away the type parameter like that.
You can try to work around that like this:
public abstract class BaseList
{
}
public class BaseList<T> : BaseList
where T : Base
{
}
Then use a List<BaseList>
Related
I want to have a class to run other classes in java, like constructor parameterized with a class to run that class later on, similar to this
class MyClass{
Class classToRun;
public MyClass(Class c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
where classToRun possible classes doesn't have a common ancestor, but all have method someStaticMethod, and have no idea about MyClass, which runs them.
But there are problems, like inner classes cannot have static methods, classes cannot be cast Class, etc.
There are solutions for parameterized with class methods, like
How do I pass a class as a parameter in Java?
Passing a class as an argument to a method in java
but not for constructors.
What is the proper solution to do this?
Use lambdas and pass the method reference: they match on the method signature. For void someStaticMethod() you can use Runnable.
class MyClass{
private final Runnable methodToRun;
public MyClass(Runnable someStaticMethod) {
methodToRun = someStaticMethod;
}
public void runClass(){
methodToRun.run();
}
}
new MyClass(SomeClass::someStaticMethod).runClass();
You cannot enforce that the method passed has the right name, but looks even neater IMHO.
You need to understand what generics are.
interface
public interface SomeInterface {
void someStaticMethod();
}
use
class MyClass<T extends SomeInterface>{
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass(){
classToRun.someStaticMethod();
}
}
As 2 of 3 answers were not to the point, I decided to publish fixed versions of both answers as far as they can be fixed.
The f1sh version from the above should like follows:
public class ClassToRunOthers {
Class classToRun;
public ClassToRunOthers(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
public static void main(String[] args) throws Exception {
ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
mc.runClass();
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
The zwei solution above can not be fixed without reflection, as generics is not to the point. Evan if you try to parametrize not with SomeInerface (because SomeClass does not extend a common SomeInterface), but with Object, it is still won't solve the problem:
public class MyClass<T extends Object> {
T classToRun;
public MyClass(T c) {
super();
this.classToRun = c;
}
public void runClass() {
// classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
}
public static void main(String[] args) {
MyClass mc = new MyClass(SomeClass.class);
}
}
class SomeClass {
static void someStaticMethod() {
System.out.println("test");
}
}
This can be fixed like the above, via reflection.
I believe, it can be done with annotations in some elegant way, and may be someone will share us with such a solution or I will do it by myself as time permits.
By now for myself, a solution with saving class name in the String in constructor next day after the question been asked did the trick.
You will have to use reflection if you want to execute a method when you only have the Class instance.
In the code below, runClass finds the method of the class using it's name as a String, then executes it. This code assumes that the method is static, also ignoring any Exception handling.
The following code prints "test":
class MyClass {
Class classToRun;
public MyClass(Class c) {
this.classToRun = c;
}
public void runClass() throws Exception {
Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
if(!method.isPresent()) {
throw new RuntimeException();
}
method.get().invoke(null);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClass mc = new MyClass(Main.class);
mc.runClass();
}
static void someStaticMethod() {
System.out.println("test");
}
}
I'm trying to convert following c# code and behavior to Java but I'm struggling to find the right syntax or programming pattern.
In c# I can use out like in interface IProxy<out Target> which allows me to implicitly cast IProxy<DerivedElement1> to IProxy<BaseElement> but for Java I'm not aware of any similar generic modifiers.
class BaseElement {
public static readonly Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 : BaseElement {
public static readonly Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 : BaseElement {
public static readonly Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
interface IProxy<out Target> {
}
class Proxy<Target> : IProxy<Target> {
}
class Program {
static void doSomething<Target>(IProxy<Target> proxy, Property<Target> property) {
// ...
}
static void Main(string[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
It is very important that the expected error appears at compile time and not at run time.
Are you aware of any applicable syntax or pattern that would allow me to implement the same behavior without any additional casting?
I hope you can point me in the right direction, thank you much for your help!
I found out that I can use Proxy<? extends Target> to declare my proxy argument.
Here is the complete solution:
class BaseElement {
public static final Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 extends BaseElement {
public static final Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 extends BaseElement {
public static final Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
class Proxy<Target> {
}
class App {
static <Target>
void doSomething(Proxy<? extends Target> proxy, Property<Target> property) {
// ...
}
static void main(String[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
If Ive got you correctly you should have a look at generic type in Java.
Sample Java Code
public class IProxy<T>{
....
}
public class Property<T>{
....
}
public class Program {
public static void doSomething(<IProxy<T> iProxy, Property<T> property){
......
}
}
Type Parameter Naming Conventions (not sure what Target is referring to in C#)
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.
I am trying to create a generic Identifier class which I would be able to use as follows:
public class TestGenericIdentifier {
public static void main(String[] args) {
Identifier<Car> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
System.out.println(carId);
System.out.println(personId);
}
}
To get there, I started by creating an Identifiable interface:
public interface Identifiable<T extends Enum> {}
The idea being that a class that implements Identifiable needs to provide an enum T in its declaration which is the type of the first parameter of the Identifier constructor:
public class Identifier<E extends Identifiable<T>> { //does not compile
public Identifier(T type, String value) {
//some code
}
}
Now the code above does not compile as I can only use Identifiable (no parameter T) on the first line. If it worked I would be able to write the following two classes:
public class Car implements Identifiable<Car.IdentifierType>{
public enum IdentifierType {
SERIAL_NUMBER,
LICENSE_PLATE;
}
}
public class Person implements Identifiable<Person.IdentifierType> {
public enum IdentifierType {
DATABASE_ID,
SOCIAL_SECURITY;
}
}
Is there a way to do that using generics?
EDIT
One way is to compromise conciseness and keep compile-time type checking by doing:
public class Identifier<T extends Enum> {
public Identifier(T type, String value) {
}
}
and the main function becomes:
Identifier<Car.IdentifierType> carId = new Identifier<>(Car.IdentifierType.LICENSE_PLATE, "123 XYZ");
Identifier<Person.IdentifierType> personId = new Identifier<>(Person.IdentifierType.SOCIAL_SECURITY, "123456");
public class Identifier<E extends Identifiable<? extends Enum>> {
public Identifier(Enum type, String value) {
//some code
}
}
Might be enough for what you want
You can get this to compile by tweaking your code a bit but I'm not sure it's what you want. The following seems to work for me.
Identifier<Car.IdentifierType, Car> carId =
new Identifier<Car.IdentifierType, Car>(Car.IdentifierType.LICENSE_PLATE,
"123 XYZ");
public static class Identifier<T extends Enum, E extends Identifiable<T>> {
public Identifier(T type, String value) {
// some code
}
}
The question is why do you want to do this? If you edit your question some more with the background, I can edit my answer to be more helpful.
package com.openwaf.test.basic;
public class MethodArgumentTest {
static interface Inf{}
static class One<E extends Inf > implements Inf{
public <T extends One> T get(T k){
return k;
}
}
static class Two<E extends Inf> extends One<E>{ }
public static void test(){
One o=new One<Inf>();
Two t=new Two<One>();
o.<Two>get(t);
}
}
Above code is just for testing purpose. IMHO it should compile without any problem ,but java compiler says
MethodArgumentTest.java:15:
get(com.openwaf.test.basic.MethodArgumentTest.One) in
com.openwaf.test.basic.MethodArgumentTest.One cannot be applied to
(com.openwaf.test.basic.MethodArgumentTest.Two)
o.get(t);
1 error
Can someone please help me out here ?
Ok, as you said this is for testing only I will not ask what this code is good for. The following one compiles but still produces a warning. You were not consequent enough defining the generics:
public class MethodArgumentTest {
static interface Inf {
}
static class One<E extends Inf> implements Inf {
public <T extends One<E>> T get(T k) {
return k;
}
}
static class Two<E extends Inf> extends One<E> {
}
public static void test() {
One<Inf> o = new One<Inf>();
Two<One<Inf>> t = new Two<One<Inf>>();
o.<Two> get(t); /* unchecked warning */
}
}
I think what you need to do is
Two tPrime= o.get(t);