5

Imagine you have a collection of classes all extending a base type:

public abstract class Vehicle{
   public Position position{get; private set;}
   public String make {get; private set;}
   public String model {get; private set;}

   public void move(integer x, integer y){
       position.translate(x,y);
   }
}

public class Bike extends Vehicle{
     public Integer speed {get; private set;}
     public Decimal tireSize {get; private set;}
     ...
}

public class Car extends Vehicle{
     public Boolean 4x4 {get; private set;}
     public Integer doors {get; private set;}
     ...
}

In your visualforce page, you want to display a collection of different Vehicles in a list but render html different for each type:

<apex:page>
  <apex:repeat var='v' value="{!vehicleCollection}">
      <div>{!v.make} - {!v.model}</div>
      <div>{!v.position}</div>
      <apex:outputPanel rendered="{! v instanceOf Bike} layout="none">
      <div>{!v['speed']}</div>
      <div>{!v['tireSize']}</div>
      <apex:outputPanel>
      <apex:outputPanel rendered="{! v instanceOf Car} layout="none">
      <div>{!v['4x4']}</div>
      <div>{!v['doors']}</div>
      <apex:outputPanel>
  </apex:repeat>
<apex:page>

Of course this doesn't work in VF... Is there an elegant solution out there? Or should I just give up on OO designs in apex and move to a flat model...

1 Answer 1

4

The "easiest" way would be to go down the dark, dark road of Dynamic Apex, because Visualforce has a problem binding to non-SObject types dynamically.

The only other alternative I can immediately think of, which just feels completely wrong, would be to include the child classes within the parent:

public abstract class Vehicle {
    public virtual Boolean getIsBike() {
        return false;
    public abstract Boolean getIsCar() {
        return false;
    }
    public Bike getBike() {
        return (Bike)this;
    }
    public Car getCar() {
        return (Car)this;
    }
}
public class Bike extends Vehicle {
    public override Boolean getIsBike() {
        return true;
    }
}

Then, you'd be able to access the properties correctly:

<apex:repeat values="{!vechicleList}" var="vehicle">
    <apex:outputText rendered="{!vehicle.isBike}">
        {!vehicle.bike.speed}
    </apex:outputText>
    <apex:outputText rendered="{!vehicle.isCar}">
        {!vehicle.car.is4x4}
    </apex:outputText>

I think you get the idea. You have to build all of the logic you need within Apex Code. Visualforce's limited ability to be dynamic is going to be particularly challenging without using actual SObject records in a wrapper class.

2
  • my current workaround similar, I just use the getIs[Type] method same as you outlined above. Instead of using the . accessor I just use the non-typesafe [] accessor (public Car getCar(){} creates a dependency on the child class and makes refactoring very hard!) I'd agree that it feels very messed up and why I was hoping someone has come up with a better solution...
    – NSjonas
    Nov 22, 2016 at 21:11
  • also, was hoping to avoid dynamic apex as I've heard horror stories.
    – NSjonas
    Nov 22, 2016 at 21:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .