What is equivalent to C # IEnumerable in Java? Covariant-capable, not Iterable

This covariance is possible in C #:

IEnumerable<A> a = new List<A>(); IEnumerable<B> b = new List<B>(); a = b; ... class A { } class B : A { } 

This is not possible in Java: (Iterable: This question discusses Java arrays and generalizations: Java is equivalent to C # IEnumerable <T> ).

 Iterable<A> a = new ArrayList<A>(); Iterable<B> b = new ArrayList<B>(); a = b; ... class A { } class B extends A { } 

With Iterable, Java Doesn't See These Two Covariance Collections

What is an iterative / enumerated interface in Java that can facilitate covariance?


Another good example of covariance, given the same class A and class B above, is allowed in both Java and C #:

  A[] x; B[] y = new B[10]; x = y; 

This feature is available in both languages ​​from their version 1. It is good that they are making progress to make this a reality in generics . C # has less friction, albeit in terms of syntax.

Covariance is mandatory for all OOP languages, otherwise OOP inheritance would be a futile exercise, for example.

  A x; B y = new B(); x = y; 

And this power should extend to generics.



Thank you all for your reply and understanding. Now reusable with covariant Java generics. This is not the syntax that some of us require, but it ( <? extends classHere> ) certainly fits the bill:

 import java.util.*; public class Covariance2 { public static void testList(Iterable<? extends A> men) { for(A good : men) { System.out.println("Good : " + good.name); } } public static void main(String[] args) { System.out.println("The A"); { List<A> team = new ArrayList<A>(); { A player = new A(); player.name = "John"; team.add(player); } { A player = new A(); player.name = "Paul"; team.add(player); } testList(team); } System.out.println("The B"); { List<B> bee = new ArrayList<B>(); { B good = new B(); good.name = "George"; bee.add(good); } { B good = new B(); good.name = "Ringo"; bee.add(good); } testList(bee); } } } class A { String name; } class B extends A {} 

Conclusion:

 The A Good : John Good : Paul The B Good : George Good : Ringo 

If anyone is interested in how it looks in C #

 using System.Collections.Generic; using System.Linq; public class Covariance2 { internal static void TestList(IEnumerable<A> men) { foreach(A good in men) { System.Console.WriteLine("Good : " + good.name); } } public static void Main(string[] args) { System.Console.WriteLine("The A"); { IList<A> team = new List<A>(); { A player = new A(); player.name = "John"; team.Add(player); } { A player = new A(); player.name = "Paul"; team.Add(player); } TestList(team); } System.Console.WriteLine("The A"); { IList<B> bee = new List<B>(); { B good = new B(); good.name = "George"; bee.Add(good); } { B good = new B(); good.name = "Ringo"; bee.Add(good); } TestList(bee); } } } class A { internal string name; } class B : A {} 
+6
source share
3 answers

Java generators allow covariance only if explicitly declared using wildcards to provide more stringent type safety. It works:

  Iterable<? extends A> a = new ArrayList<A>(); Iterable<B> b = new ArrayList<B>(); a = b; 

However, note that now you cannot add anything through the a link, because it has declared that it contains instances of some specific but unknown class, which may be A or any subclass of it. The behavior of wildcards is often contrary to intuition and can be very complex, so they should be used in moderation.

+7
source

Generators are not covariant in Java. You will have to do it the old way, as it was when C # did not support covariance in generics.

However, in Java, you can pretend that a generic iterable is something iterable, denoted by a question mark. The list of everything contains only objects.

 Iterable<A> a = new ArrayList<A>(); Iterable<?> b = a; 
+2
source

There is a good reason why such covariance in tribal collections is a bad idea:

Suppose you:

 ArrayList<A> a = new ArrayList<A>(); ArrayList<B> b = new ArrayList<B>(); a.add(new A()); b = a; B item=b.get(0); 

Oops - a function designed to return only objects of type B, returned type A. This obviously will not work. Therefore, the Java compiler prohibits it for type safety.

It’s not so difficult: simple workarounds are to simply use non-generic classes or limit the general argument of the type to the general superclass (in this case).

0
source

Source: https://habr.com/ru/post/916154/


All Articles