7

I am working with insurance and have two different policy types - motor and household, represented by two different classes, Motor and Household.

Both have several bits of data in common, so both would inherit from another class called Policy. When a user logs into the app, they could have either a motor or a household policy, so the app needs to display the generic information and the information unique to Motor or Household. To encapsulate all this, i have a response object that has both a Motor member and a Household member, as shown below:

public class Response
{
    ...
    private MotorPolicy                 _motorPolicy;
    private HouseholdPolicy             _householdPolicy;
    ....
}

The code below should demonstrate:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{
    lblDescription.Text = response.MotorPolicy.Description;
    lblReg.Text = response.MotorPolicy.Reg;
}
else
{
    lblDescription.Text = response.HouseholdPolicy.Description;
    lblContents.Text = response.HouseholdPolicy.Contents;
}

The MotorPolicy doesn't have Contents property and the HouseholdPolicy doesn't have a Reg property.

But I really want to simply do:

if (response.PolicyType == Enumerations.PolicyType.Motor) 
{
    lblDescription.Text = response.Policy.Description;
    ...
}

I have tried using generics, could couldn't find the right solution.

13 Answers 13

5

Your response only needs a Policy type, you can then store a MotorPolicy or HouseholdPolicy type into it.

Then your response just needs to check for data type

if (response.Policy is MotorPolicy) ....

Alternatively have an abstract method or a property returning data from an abstract method on the Policy type that is fully inplemented by the child classes and returns reg data or contents data as apporpriate.

Sign up to request clarification or add additional context in comments.

2 Comments

Note that if you pursue this path, you may end up writing a lot of "if/then" or "switch" statements to handle the processing based on type. In this case, you'll want to consider a pattern called "Replace Conditional With Stratgy" informit.com/articles/article.aspx?p=1398607&seqNum=2
He could also create a Dictionary<Type, Action<Policy>> which maps each policy type to a seperate handler method.
5

Each Policy descendant (now you have two, you might have more in the future, right?) should have their own UI controls which "know" how to deal with the policy information. The same approach can be used for other things, such as a "controller" for policy objects etc.

The response can then be made generic:

public class Response<T> where T: Policy {
    ...
    private T _policy;
    ....
}

Alternatively, you could have a more generic approach which uses reflection to display the information, but those are usually less "sexy" in their appearance and usability (think of the Property Grid in the VS designer).

1 Comment

I agree with the UI controls.
1
public interface IPolicy
{
    string Description { get; }
    string Reg { get; }
    string Contents { get; }
}

public class MotorPolicy : IPolicy
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return ...; }
    }

    public string Contents
    {
        get { return String.Empty; }
    }
}

public class HousholdPolicy : IPolicy
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return String.Empty; }
    }

    public string Contents
    {
        get { return ...; }
    }
}

public class Response
{
    ...
    private IPolicy             _policy;
    ....
}

Now you don't need an Enumeration to show which type you've implemented, you can just say

lblDescription.Text = response.Policy.Description;
lblReg.Text = response.Policy.Reg;
lblContents.Text = response.Policy.Contents;

Edit: Alternate solution

public interface IPolicy
{
    string Description { get; }
}

public interface IHasReg
{
    string Reg { get; }
}

public interface IHasContents
{
    string Contents { get; }
}

public class MotorPolicy : IPolicy, IHasReg
{
    public string Description
    {
        get { return ...; }
    }

    public string Reg
    {
        get { return ...; }
    }
}

public class HouseholdPolicy : IPolicy, IHasContents
{
    public string Description
    {
        get { return ...; }
    }

    public string Contents
    {
        get { return ...; }
    }
}

public class Response
{
    ...
    private IPolicy             _policy;
    ....
}

This leaves you with more code in the calling function

lblDescription.Text = response.Policy.Description;
IHasReg hasReg = response.Policy as IHasReg;
if (hasReg != null) lblReg.Text = hasReg.Reg;
IHasContents hasContents = response.Policy as IHasContents;
if (hasContents != null) lblContents.Text = hasContents.Contents;

but is considerably more extensible than other options presented and complies with your desire to avoid functionality in the implementation which doesn't make sense.

2 Comments

This is what i thought to start with, but just didn't like how my householdPolicy would contain Reg, and MotorPolicy would contain Contents. Would really like to have a policy object that, based on the data obtained, would have just one or the other.
@Chris - I would look at that the other way around. Your Response NEEDS a description, a reg and contents, thus any Policy implementation should provide that data, hence the interface. The concrete implementations deliberately return String.Empty in the fields that don't apply to that type of policy.
1

One option is to add a member to Policy that synthesizes all the derived class' relevant properties to provide a summary:

 public abstract class Policy {
     public string Description { get; set; }
     public abstract string Summary { get; }
 }

 public class MotorPolicy: Policy {
     public override string Summary {
         get { return this.Description + "\r\n" + this.Reg; }
     }
 }

 public class HouseholdPolicy: Policy {
     public override string Summary {
         get { return this.Description + "\r\n" + this.Contents; }
     }
 }

This centralizes the logic and makes the user interface code simple:

 label.Description.Text = response.Policy.Summary;

That basic implementation sacrifices the ability to format the subsections separately. You could overcome that by exposing the summary as a collection of strings:

public abstract IEnumerable<string> SummarySections { get; }

If you want to display the derived classes' details in fundamentally different ways, you'll have to embrace the conditional logic in the user interface layer (for example, you might list the household policy's contents in a table, but show a scanned image for the motor policy's registration).

Comments

1

Use the template pattern:

Create a base class called Policy with a virtual abstract get method to determine the description of the policy.

public abstract class Policy
{ 
    protected virtual string GetDescription()
    {
         return string.Empty()    
    }

    public string Description 
    { 
        get 
        {
           return GetDescription();
        } 
    }
}

public MotorPolicy : Policy
{
    public override string GetDescription()
    {
       return ..... ////specific description implementation for MotorPolicy
    }
}

public HouseHoldPolicy : Policy
{
    public override string GetDescription()
    {
       return ..... ////specific description implementation for HouseholdPolicy
    }
}


public class Response        
{        
    ...        
    private MotorPolicy                 _motorPolicy;        
    private HouseholdPolicy             _householdPolicy; 
    private PolicyType                  _policyType;       
    ....        

    public Policy Policy
    {
        get
        {
           if (_policyType== PolicyType.Motor) 
           {
              return _motorPolicy;
           } 
           if (_policyType== PolicyType.Household) 
           {
              return _householdPolicy;
           } 

           return null;
        }
    }        
}    

client code:

if (response.Policy != null)        
{       
    lblDescription.Text = response.Policy.Description;       
    ...       
}    

Let MotorPolicy and HouseholdPolicy derive from Policy and override the abstract get method from the base and create a specific implementation of it.

In the Response class just get the description.

Comments

0

The simplest solution would be to implement an interface with a description property and a "contents" property, and then in your motor policy class, create a dummy "contents" property which returns "reg".

Comments

0

Can your response contain either a MotorPolicy or a HouseholdPolicy or, can it contain one of each?

If you are dealing with one or the other then create a base type that both classes inherit that defines the common properties. When you output the common properties just cast the Policy as the base type and use that.

1 Comment

It does contain both a HouseholdPolicy and a MotorPolicy, but then i have to refer to even my description as response.MotorPolicy.Description and response.HouseholdPolicy.Description for common properties. I realy want to just have response.Policy.Description so i am not nearly duplicating code.
0

My immediate thought is to go for:

public abstract class Response
{
  public abstract Policy Policy {get;}//can be used for stuff for dealing with all policies.
  public static Response GetResponse(Policy policy)
  {//factory method
    if(policy is MotorPolicy)
      return new MotorResponse((MotorPolicy)policy);
    if(policy is HouseholdPolicy)
      return new HouseholdResponse((HouseholdPolicy)policy);
    throw new ArgumentException("Unexpected policy type");
  }
}
public class MotorResponse : Response
{
  private readonly MotorPolicy _motorPolicy;
  public MotorResponse(MotorPolicy policy)
  {
    _motorPolicy = policy;
  }
  protected override Policy Policy
  {
    get { return _motorPolicy; }
  }
  // motor specific stuff
}
public class HouseholdResponse : Response
{
  private readonly HouseholdPolicy _householdPolicy;
  public HouseholdResponse(HouseholdPolicy policy)
  {
    _householdPolicy = policy;
  }
  protected override Policy Policy
  {
    get { return _householdPolicy; }
  }
  // household specific stuff
}

7 Comments

Why do you favor explicit fields etc. instead of using a generic base class?
I don't, but i am not that familiar with generics, especially using them as base classes, and i couldn't get that solution to work. Do you know how??
@Lucero, I wouldn't argue for generics here (based on what we know of the problem), because right now what commonality I can see as useful in Response depends upon the commonality in policy, and if I was to have Response<T> where T:Policy then I'd still have to derive from Response<HouseholdPolicy> to provide the extras needed. Really, a generic base class doesn't add much extra, and then it does block any runtime polymorphism.
If i went with this solution, then wouldn't i just have two different types of response objects, so i'd be back in the situation i am in now, except with response instead of policy.
@Jon, that was the problem i cam across when i tried a generic solution.
|
0

I would try something like this:

  public class Response
  {
     public Policy SelectedPolicy {get;set;}

     //I don't think you need these, but hard to 
     //say without seeing the rest of the code
     ...
     private MotorPolicy                 _motorPolicy;
     private HouseholdPolicy             _householdPolicy;
     ....
  }

then

lblDescription.Text = response.SelectedPolicy.Description;

if (SelectedPolicy is MotorPolicy)
    lblReg.Text = ((MotorPolicy)response.SelectedPolicy).Reg;

else if (SelectedPolicy is HouseholdPolicy)
    lblContents.Text = ((HouseholdPolicy)response.SelectedPolicy).Contents;

I would not put both Reg and Contents in the base class or interface. If I do what's the purpose of inheritance if all classes look the same? The only benefits I would get would be types, and that's not going to gain me much in this case.

Comments

0

maybe I don't understand the question but I would just use inheritence

define policy as

public class Policy { public string Description{ get; set;} public string Details {get; set;}

}

public class MotorPolicy:Policy 
{
    public void SetReg(string reg)
    {
        base.Details = reg;
    }
}

public class HousePolicy:Policy 
{
    public void SetContents(string contents)
    {
        base.Details = contents;
    }
}

and call by

    private void Form1_Load(object sender, EventArgs e)
    {
        MotorPolicy mp = new MotorPolicy();
        mp.Description = "Motor";
        SetForm(mp);       
    }

    private void SetForm(Policy p)
    {
        lblDescription.Text = p.Description;
        lblDetail.Text = p.Details;

        //then if you still need specifics 
        if (p.GetType() == typeof(MotorPolicy))
        {
            MotorPolicy mp = p as MotorPolicy;
            //continue assigning mp
        }
        else if (p.GetType() == typeof(HousePolicy))
        {
            HousePolicy hp = p as HousePolicy;
            //continue assigning Hp
        }
    }

Note I put reg/contents as a field detail as they are both string types. If one was int vs string then they would have to be done separate.

Comments

0

define the Policy interface and implement it in your both the policy classes

Interface IPolicy{
    int Reg {get;set;};
    string Contents {get;set;};
}

MotorPolicy : Policy,IPolicy {

 string IPolicy.Contents 
     {get;set;};


 int IPolicy.Reg 
     {get;set;};

}

HouseholdPolicy : Policy , IPolicy {
 string IPolicy.Contents 
     {get;set;};


 int IPolicy.Reg 
     {get;set;};
}

4 Comments

He has a baseclass called Policy, using a interface instead would change nothing.
That's not really how I understand good oo design. Household policies don't have a reg number, and motor policies don't have contents. Therefore the design is misleading
OK.. then he can OP can define like this another way.. MotorPolicy : Policy, IPolicy
Ramesh, how would that work inheriting from both the base class and the interface?
0

Yours is a unique example of "Refactoring condition to Polymorphism" [Fowler].

And then your method should accept the proper object and do as below:

public void Update(IPolicy policy)
{
        lblDescription.Text = policy.Description;
        lblReg.Text = .Reg;

}

Comments

0

Well, I dislike abstract classes so I went with an interface for Policy

public interface IPolicy
{
    string Description { get; set;}
    void Display();
}

Then we inherit from it to create MotorPolicy

public class MotorPolicy : IPolicy
{
    public string Description { get; set; }
    public string Reg { get; set; }

    public void Display()
    {
        Console.WriteLine(string.Format("Description: {0}", Description));
        Console.WriteLine(string.Format("Reg: {0}", Reg));
    }
}

Then for response I changed the Policy to a List in the off chance that you can have both or either. Now we've offloaded the handling of displaying the data to the specific policy itself.

public class Response
{
    public List<IPolicy> Policies { get; set; }

    public void Display()
    {
        Policies.ForEach(p => p.Display());
    }

    public void Display(Type t)
    {
        var policy = (from p in Policies
                      where p.GetType() == t
                      select p).FirstOrDefault();
        policy.Display();
    }
}

This could easily be changed to not use the List and we can get rid of the overloaded Display.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.