强制接口实现在c#中实现层次结构

时间:2022-04-26 05:00:02

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.

所以我想在我的ICar,IWheels和IRims的接口实现中强制使用这个层次结构。

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

所以我做了这样的事情(在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.

也许在我的问题中有一些不精确的东西,或者我错过了一些重要信息。如果是,请在评论中提问。

6 个解决方案

#1


10  

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).

在您的界面中,您必须明确Wheels应该是ICar的属性,因为您无法声明接口实现应该具有哪些字段。 (字段是内部工作,因此接口不应该知道它)。

interface ICar
{
    IWheels Wheels
    {
       get;
    }
}

#2


7  

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:

你可能只想把getter放在接口中 - 在接口中包含一个setter有点不寻常:

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.)

(如果你想要覆盖一个只有getter来添加setter的现有(或抽象)属性,那就有些奇怪了,但我相信也可以用setter实现一个“getter-only”接口。)

#3


4  

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; }
}

#4


4  

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; }
}

#5


0  

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...

我并不习惯C#,但听起来你可以通过使用你想要使用的字段制作抽象类来强制实现。因此,如果您扩展这些抽象类,您将获得其中的字段。你必须创建一个抽象类和一个接口...

#6


0  

Here it is a fully functional 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());
        }
    }
}

#1


10  

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).

在您的界面中,您必须明确Wheels应该是ICar的属性,因为您无法声明接口实现应该具有哪些字段。 (字段是内部工作,因此接口不应该知道它)。

interface ICar
{
    IWheels Wheels
    {
       get;
    }
}

#2


7  

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:

你可能只想把getter放在接口中 - 在接口中包含一个setter有点不寻常:

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.)

(如果你想要覆盖一个只有getter来添加setter的现有(或抽象)属性,那就有些奇怪了,但我相信也可以用setter实现一个“getter-only”接口。)

#3


4  

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; }
}

#4


4  

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; }
}

#5


0  

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...

我并不习惯C#,但听起来你可以通过使用你想要使用的字段制作抽象类来强制实现。因此,如果您扩展这些抽象类,您将获得其中的字段。你必须创建一个抽象类和一个接口...

#6


0  

Here it is a fully functional 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());
        }
    }
}