Skip to main content

It would be really useful to support covariant return types alongside this. That way, we can have generics in a class hierarchy where fluent methods can return the correct types. 

 

For example, consider an example in Java where we want to define a custom list type with a generic type T (MyList<T> in the example).  There may well be things that we want to do differently when we know that we have a list of SObjects (for example, have a method to do a database update). 

 

In the example below, the fluent method, add(), returns "this". SObjectList can override add() to return itself rather than a MyList, keeping the right context as we call add() a number of times. 

 

That pattern is not currently possible in Apex because it does not support covariant return types (https://ideas.salesforce.com/s/idea/a0B8W00000GdXOCUA3/support-covariant-return-types-in-apex). 

 

public class Main {

public static void main(String[] args) {

MyList<Integer> intList = new MyList<Integer>()

.add(3)

.add(5);

System.out.println("ints: " + intList.toString());

SObjectList<Account> accountList = new SObjectList<Account>()

.add(new Account("Foo"))

.add(new Account("Bar"))

.doUpdate();

System.out.println("SObjects: " + accountList.toString());

}

static class SObject {

@Override

public String toString() {

return "Hi, I'm an SObject";

}

}

static class Account extends SObject {

private final String name;

public Account(String name) {

this.name = name;

}

@Override

public String toString() {

return "Account Name: " + name;

}

}

static class MyList<T> {

private final List<T> theList;

public MyList() {

theList = new ArrayList<T>();

}

public MyList<T> add(T toAdd) {

theList.add(toAdd);

return this;

}

public String toString() {

return theList.stream().map(Objects::toString).collect(Collectors.joining(", "));

}

}

static class SObjectList<T extends SObject> extends MyList<T> {

public SObjectList() {

super();

}

@Override

public SObjectList<T> add(T toAdd) {

super.add(toAdd);

return this;

}

public SObjectList<T> doUpdate() {

System.out.println("Do a database update!");

return this;

}

}

}

0/9000