views:

487

answers:

6

I m writing interfaces for new project and would like to get some advice.

I have a class that have a subclass and it has a subclass. The tree of this classes is like this:

Class Car
{
    Wheels Wheel;
}
Class Wheels
{
    Rims Rim;
}

So to simplify: one car has one wheel and one wheel has one rim. (cant make up other better example, sorry).

So I would like to force this hierarchy in my interface implementation of ICar, IWheels and IRims.

So i did something like this (in C#):

ICar
{
  IWheels Wheel;
}
IWheels
{
  IRims Rim;
}

And i have a error that I can not have fields in interface implementation. So this started me thing that maybe it's wrong interface design. I would like to force interface implementations to implement this kind of hierarchy. But maybe accorting to design patterns and best practices it should be done in other way?

Could you please tell me how to design my system so that objects will be forced to implement this kind of hierarchy?

Maybe there is something not precise in my question or I missing some important info. If yes, please ask in comments.

+9  A: 

In your interface, you'll have to make it clear that Wheels should be a property of ICar, since you cannot declare which fields an interface implementation should have. (Fields are inner workings, so the interface should not know about it).

interface ICar
{
    IWheels Wheels
    {
       get;
    }
}
Frederik Gheysels
+2  A: 

As the error says, you can't specify fields in your interfaces. You can specify properties though:

interface ICar
{
    IWheels Wheel { get; set; }
}

interface IWheels
{
    IRims Rim { get; set; }
}
LukeH
+4  A: 

You can't specify a field in an interface (and you shouldn't be able to - that's an implementation decision) but you can specify a property:

public interface ICar
{
    IWheels Wheel { get; set; }
}

public interface IWheels
{
    IRims Rim { get; set; }
}

You may well want to only put the getter in the interface though - it's slightly unusual to include a setter in an interface:

public interface ICar
{
    IWheels Wheel { get; }
}

public interface IWheels
{
    IRims Rim { get; }
}

(There are oddities if you want to override an existing (or abstract) property which only has a getter to add a setter, but it's okay to implement a "getter-only" interface with setters as well, I believe.)

Jon Skeet
+2  A: 

You can't declare fields, but you can declare properties. That will have the same end effect of forcing a particular class to provide an instance of another class.

ICar
{
  IWheels Wheel { get; set; }
}
IWheels
{
  IRims Rim { get; set; }
}
JaredPar
A: 

I'm not so much used to C# but it sounds to me that you can force that implementation by making Abstract classes, with the fields you want to use. So if you extend those abstract classes you will have the fields in them available. You'll have to make an abstract class AND an interface though...

Juan Manuel
A: 

Here it is a fully fucntional code... Hope it helps...

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication10
{
    //Interfaces

    public interface ICar
    {
        string name { get;}
        IWheel wheel { get;}
    }


    public interface IWheel
    {
        string brand { get;}
    }

    //Implementations

    public class Michelin : IWheel
    {
        #region IWheel Members

        public string brand
        {
            get { return "michelin"; }
        }

        #endregion
    }


    public class Toyota : ICar
    {
        Michelin m = new Michelin();
        #region ICar Members

        public string name
        {
            get { return "toyota"; }
        }

        public IWheel wheel
        {
            get { return m; }
        }

        #endregion
    }

    //A user of the interfaces. Only cares about ICar but knows implicitly about IWheel

    public class Stand
    {
        public Stand()
        {
            cars = new List<ICar>(2);
            cars.Add(new Toyota());
            cars.Add(new Toyota());
        }
        List<ICar> cars;

        public string ShowCars()
        {
            StringBuilder str = new StringBuilder();
            foreach (ICar iterCar in cars)
            {

                str.AppendLine(string.Format("car {0} with wheel {1}",
                    iterCar.name, iterCar.wheel.brand));
            }
            return str.ToString();
        }
    }

    //entry point. creates a stand and shows the cars, testing that properties are visible
    class Program
    {
        static void Main(string[] args)
        {
            Stand myLittleStand = new Stand();
            Console.WriteLine(myLittleStand.ShowCars());
        }
    }
}
Luis Filipe
Of course, following best-practices properties should be Upper Case and strings shouldn't be hard coded but i think those are minor details
Luis Filipe