Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using interface to differentiate implementation

Tags:

c#

oop

interface

Here is my specific scenario with an interface and its implementation:

IPerson {string Name;}

American : IPerson {string Name;}
Asian : IPerson {string Name;}
European : IPerson {string Name;}

People = new List<IPerson>(); // This list can have American, Asian and/or European

When I access People list I need to make distinction between American, Asian and European and they can share the same interface. Is it good to use additional interfaces (IAmerican, IAsian, IEuropean) which all implements IPerson and use that to differentiate between the implementing class like:

IAmerican : IPerson {}
IAsian : IPerson {}
IEuropean : IPerson {}

American : IAmerican {string Name;}
Asian : IAsian {string Name;}
European : IEuropean {string Name;}

People = new List<IPerson>();
People.Add(new American());
People.Add(new Asian());
People.Add(new European());

var americans = People.OfType<IAmerican>(); // Getting all Americans from People

New Interfaces aren't of much use but to segregate the objects. Is this a good approach or should I implement some type property in IPerson to differentiate its implementation?

like image 661
rageit Avatar asked Nov 20 '13 19:11

rageit


3 Answers

You don't have to do your second step, your first one should work as well.

void Main()
{
    var people = new List<IPerson>();
    people.Add(new American { Name = "jack"});
    people.Add(new American { Name = "John"});
    people.Add(new Asian { Name = "ho"});

    Console.WriteLine (people.OfType<American>());

}

public interface IPerson {
    string Name {get; set;}
}

class American : IPerson {public string Name {get; set; }}
class Asian : IPerson {public string Name {get; set; }}
class European : IPerson {public string Name {get; set; }}

Output:

jack
john

The list defines every object as their common denominator (IPerson), but that doesn't mean it loses track of the actual object. I don't see the need to create obsolete interfaces.

That being said: I would prefer composition over inheritance here. What separates an American from a European? Keep a property in the Person class (make it a class instead of an interface) that indicates a person's regionality.

like image 74
Jeroen Vannevel Avatar answered Nov 11 '22 01:11

Jeroen Vannevel


Types are not only available discriminators. You can just ask the object directly:

enum Continent { Europe, Asia, America }

public interface IPerson 
{  
    string Name { get; set; }
    Continent Continent { get; set; }
}

public class Asian : IPerson
{
    public Continent Continent
    {
        get 
        {
           return Continent.Asia;
        }
    }
}

This is what interfaces are about - classes implement their functionality in their own specific way.

like image 21
Wiktor Zychla Avatar answered Nov 11 '22 03:11

Wiktor Zychla


I would go with a property.

enum PersonType
{
    American, Asian, European
}

interface IPerson
{
    string Name { get; set; }
    PersonType Type { get; }
}

American : IPerson
{
    public string Name { get; set; }
    public PersonType Type { get { return PersonType.American; } }
}

And querying for Americans:

var americans = People.Where(p => p.Type == PersonType.American);

You should probably find a better name for that enum, but the concept is important here, not the name.

like image 24
MarcinJuraszek Avatar answered Nov 11 '22 02:11

MarcinJuraszek