Joris Mathijssen
Joris Mathijssen

Reputation: 669

List with multiple derived object. How to acces the fields in the derived

Currently i'm working with a Base class called "JourneyLeg". This base class has 5 derived that all inherit from the base class. two of these classes are called "WalkingLeg" and "VehicleLeg". These 2 derived classes both contain a "from" and "to" field. The other 3 don't.

List<JourneyLeg> legs

I now have list with all kind of derived objects in it. Some of them are Walkingleg, some of them are vehicleleg and the rest are one of the 3 other derived classes. The list is defined as above.

I want to loop through the complete list and do actions only for the walking and vehicle objects. These actions include accessing the "from" and "to". These 2 fields are only available in these 2 derived classes and not in the base class.

The only way i can think of is checking if it is one of the 2 derived classes and then doing the actions (See below). But this way i have so much duplicate code. I think i can't extract the duplicate code in a method because then the parameter object we give to this method would be VehicleLeg or WalkingLeg and cant be both.

case VehicleLeg vehicleLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(vehicleLeg.To.LatLong, vehicleLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(vehicleLeg.From.LatLong, vehicleLeg.From.IsVisible);

    directionsRequestJourneyleg.id = vehicleLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = vehicleLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = vehicleLeg.To.Time.Planned;

    directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Vehicle;
    directionsRequestJourneyleg.Modality = vehicleLeg.Modality;
    break;
}
case WalkingLeg walkingLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(walkingLeg.To.LatLong, walkingLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(walkingLeg.From.LatLong, walkingLeg.From.IsVisible);


    directionsRequestJourneyleg.id = walkingLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = walkingLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = walkingLeg.To.Time.Planned;
    directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Walking;
    break;
}

I'm probably missing something easy here. But i cant wrap my head around it. I hope someone can get me back on the right track.

Below here are the classes:

/// <summary>
/// JourneyLeg is the base class used to define commonalities between:
/// 
/// *VehicleLeg, WalkingLeg, TransitionLeg, AdvertisementLeg*
/// </summary>
public class JourneyLeg
{
    [Required]
    public string Id { get; set; }
    [Required]
    public LegType Type { get; set; }
}
/// <summary>
/// Vehicle leg model
/// </summary>
public class VehicleLeg : JourneyLeg
{
    [Required]
    public ModalityType Modality { get; set; }
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
}
/// <summary>
/// Walking leg model
/// </summary>
public class WalkingLeg : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
    /// <summary>
    /// Displays the total walk time in minutes and in parenthese the distance in meters
    /// </summary>
    [Required]
    public string Description { get; set; }
}

Upvotes: 3

Views: 367

Answers (2)

Camilo Terevinto
Camilo Terevinto

Reputation: 32078

I would just add an intermediary class that adds the From and To properties:

public class JourneyLeg
{
    [Required]
    public string Id { get; set; }

    [Required]
    public LegType Type { get; set; }
}

// You may want another name...
public class JourneyFromToLeg : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }

    [Required]
    public LegStop To { get; set; }
}

public class VehicleLeg : JourneyFromToLeg 
{
    [Required]
    public ModalityType Modality { get; set; }
}

public class WalkingLeg : JourneyFromToLeg 
{
    [Required]
    public string Description { get; set; }
}

So you can then use:

case JourneyFromToLeg fromToLeg:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(fromToLeg.To.LatLong, fromToLeg.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(fromToLeg.From.LatLong, fromToLeg.From.IsVisible);


    directionsRequestJourneyleg.id = fromToLeg.Id;
    directionsRequestJourneyleg.From = legFrom;
    directionsRequestJourneyleg.To = legTo;
    directionsRequestJourneyleg.LegArrival = fromToLeg.From.Time.Planned;
    directionsRequestJourneyleg.LegDeparture = fromToLeg.To.Time.Planned;

    // you may want to think a little more of this too
    if (fromToLeg is WalkingLeg)
    {
        directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Walking;
    }
    else
    {
        directionsRequestJourneyleg.Type = DirectionsRequestJourneyLegType.Vehicle;
        directionsRequestJourneyleg.Modality = ((VehicleLeg)fromToLeg).Modality;            
    }

    break;
}

You could otherwise have IFromLeg/IToLeg/IFromToLeg interfaces if you'd prefer to use interface inheritance

Upvotes: 2

Blam
Blam

Reputation: 2965

Make a new class JourneyLegFromTo or similar that inherits JourneyLeg, then make VehicleLeg and WalkingLeg inherit from the new class.

Then you can reduce the code down to checking if it's a JouneyLegFromTo instead of the two cases, and you'll be able to access the from and two fields.

public class JourneyLegFromTo : JourneyLeg
{
    [Required]
    public LegStop From { get; set; }
    [Required]
    public LegStop To { get; set; }
}

public class WalkingLeg : JourneyLegFromTo 
{
    ...
}

public class VehicleLeg : JourneyLegFromTo 
{
    ...
}

Later on:

case JourneyLegFromTo journeyLegFromTo:
{
    var legTo = new DirectionsRequestJourneyLegsLocation(journeyLegFromTo.To.LatLong, journeyLegFromTo.To.IsVisible);
    var legFrom = new DirectionsRequestJourneyLegsLocation(journeyLegFromTo.From.LatLong, journeyLegFromTo.From.IsVisible);
    ...

Upvotes: 2

Related Questions