Skip to content

Instantly share code, notes, and snippets.

@childnode
Last active October 13, 2015 11:59
Show Gist options
  • Save childnode/f1ea31c9489d3ce95904 to your computer and use it in GitHub Desktop.
Save childnode/f1ea31c9489d3ce95904 to your computer and use it in GitHub Desktop.
Generics and inheritance of classes in Java and C#
using System;
using System.Collections.Generic;
public class BaseClass
{
}
public class DerivedClassA : BaseClass
{
}
class Signal<T> where T : class
{
public void Dispatch(T obj)
{ }
}
class CoolSignal : Signal<Container<BaseClass>>
{
}
public class Container<T>
where T : BaseClass
{
}
public class BaseContainer : Container<BaseClass>
{
}
public class DerivedContainer : Container<DerivedClassA>
{
}
class TestAssignable
{
public BaseClass DerivedAssignableToBase()
{
return new DerivedClassA() as BaseClass;
}
public Container<BaseClass> DerivedContainerNotAssignableToBaseContainer()
{
return new DerivedContainer() as BaseContainer;
}
}
class CoolMediator<T> where T : BaseClass
{
protected Container<T> Data;
protected CoolSignal Signal;
public void Test()
{
Signal.Dispatch(Data);
}
}
class CoolDerivedMediator : CoolMediator<DerivedClassA>
{
public void Test2()
{
Signal.Dispatch(Data);
}
}
using System;
using System.Collections.Generic;
public class BaseClass
{
}
public class DerivedClassA : BaseClass
{
}
class Signal<T> where T : class
{
public void Dispatch(T obj)
{ }
}
class CoolSignal : Signal<IContainer<BaseClass>>
{
}
/// <summary>
/// using covariance
/// </summary>
internal interface IContainer<out T>
where T : BaseClass
{
}
public class Container<T> : IContainer<T>
where T : BaseClass
{
}
public class BaseContainer : Container<BaseClass>
{
}
public class DerivedContainer : Container<DerivedClassA>
{
}
class TestAssignable
{
public BaseClass DerivedAssignableToBase()
{
return new DerivedClassA() as BaseClass;
}
/// <summary>
/// not working
/// </summary>
/// <returns></returns>
public Container<BaseClass> DerivedContainerNotAssignableToBaseContainer()
{
return new DerivedContainer() as BaseContainer;
}
/// <summary>
/// not working
/// </summary>
/// <returns></returns>
public IContainer<BaseClass> DerivedContainerNotAssignableToBaseContainer2()
{
IContainer<DerivedClassA> foo = new Container<DerivedClassA>();
return foo;
}
/// <summary>
/// not working, since a covariance is not valid for classes but only interfaces and delegates
/// </summary>
/// <returns></returns>
public Container<BaseClass> DerivedContainerNotAssignableToBaseContainer2()
{
return new Container<DerivedClassA>();
}
/// <summary>
/// working as of .net4
/// </summary>
/// <returns></returns>
public IEnumerable<BaseClass> CovarianceExample()
{
IEnumerable<DerivedClassA> d = new List<DerivedClassA>();
IEnumerable<BaseClass> b = d;
return b;
}
}
class CoolMediator<T> where T : BaseClass
{
protected Container<T> Data;
protected CoolSignal Signal;
public void Test()
{
Signal.Dispatch(Data);
}
}
class CoolDerivedMediator : CoolMediator<DerivedClassA>
{
public void Test2()
{
Signal.Dispatch(Data);
}
}
public class Outer {
public class BaseClass {
}
public class DerivedClassA extends BaseClass {
}
class Signal<T> {
public void Dispatch(T obj) {
}
}
class CoolSignal extends Signal<Container<BaseClass>> {
}
public class Container<T extends BaseClass> {
}
public class BaseContainer extends Container<BaseClass> {
}
public class DerivedContainer extends Container<DerivedClassA> {
}
class TestAssignable {
public BaseClass DerivedAssignableToBase() {
return (BaseClass) (new DerivedClassA());
}
public Container<BaseClass> DerivedContainerNotAssignableToBaseContainer() {
return (BaseContainer) (new DerivedContainer());
}
}
class CoolMediator<T extends BaseClass> {
protected Container<T> Data;
protected CoolSignal Signal;
public void Test() {
Signal.Dispatch(Data);
}
}
class CoolDerivedMediator extends CoolMediator<DerivedClassA> {
public void Test2() {
Signal.Dispatch(Data);
}
}
}
public class Outer {
public class BaseClass {
}
public class DerivedClassA extends BaseClass {
}
class Signal<T> {
public void Dispatch(T obj) {
}
}
class CoolSignal extends Signal<Container<? extends BaseClass>> {
}
public class Container<T extends BaseClass> {
}
public class BaseContainer extends Container<BaseClass> {
}
public class DerivedContainer extends Container<DerivedClassA> {
}
class TestAssignable {
public BaseClass DerivedAssignableToBase() {
return (BaseClass) (new DerivedClassA());
}
public Container<? extends BaseClass> DerivedContainerNotAssignableToBaseContainer() {
return new DerivedContainer();
}
public Container<? extends BaseClass> DerivedContainerNotAssignableToBaseContainer2() {
return new Container<BaseClass>();
}
public Container<? extends BaseClass> DerivedContainerNotAssignableToBaseContainer3() {
return new BaseContainer();
}
}
class CoolMediator<K extends Container <? extends BaseClass>> {
protected K Data;
protected CoolSignal Signal;
public void Test() {
Signal.Dispatch(Data);
}
}
class CoolDerivedMediator extends CoolMediator<DerivedContainer> {
public void Test2() {
Signal.Dispatch(Data);
}
}
}
@childnode
Copy link
Author

some notes

what is available in Java what C# can't:

  • wildcards
    • Bounded wildcard type List<? extends Number>
    • Unbounded wildcard type List<?>
    • ? super Class

TO BE DISCUSSED see

=> see GenericsAndInheritanceJavaTwo_usingWildcards.java
covariance allows what java does implicit by using bounded wildcard type

details on

what is available in C# what Java can't:

  • new() constraint
  • contravariance

Bounded type parameter in Java <E extends Number> equivalents to <E> where E : Number

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment