【问题标题】:Is it a good practice to add public methods in a class which are not in Interface definition? When should I do that?在接口定义中没有的类中添加公共方法是一种好习惯吗?我什么时候应该这样做?
【发布时间】:2014-11-12 10:39:54
【问题描述】:

对 OOP 概念不是很清楚,可能是一个愚蠢的问题,请忽略它的愚蠢:-)

这个问题与下面的课程有关。在那里我添加了一个公共方法“TestMethod()”,该方法未在接口中定义(如下)。

  1. 这是一种不好的做法吗?是否所有方法都必须在接口中定义?
  2. 在哪些情况下,我可以在类中实现公共方法/成员,但不能在接口中实现?

界面...

public interface IAnimals
{
    void MakeNoise(string noise);
    void Move();
    string Color
    {
        get;
        set;
    }
}

类实现...

class Animal : IAnimals
{
    private string color;
    string IAnimals.Color
    {
        get
        {
            return color;
        }
        set
        {
            color = value;
        }
    }
    void IAnimals.MakeNoise(string noise)
    {
        Console.WriteLine("Animal " + noise);
    }
    void IAnimals.Move()
    {
        Console.WriteLine("Animal moves");
    }
    public void TestMethod()
    {
        Console.WriteLine("test method in Animal class");
    }
}

程序...

class Program
{
    static void Main(string[] args)
    {
        //Animal1 show methods and properties defined in the Interface
        IAnimals animal1 = new Animal();

        //Animal2 only shows the public method of Animal class
        Animal animal2 = new Animal(); 

        animal1.Color = "Red";
        Console.WriteLine("Animal's color is " + animal1.Color);
        animal1.MakeNoise("Barks");
        animal1.Move();


        animal2.TestMethod();

        Console.ReadLine();
    }
}

还有输出...

动物的颜色是红色

动物吠声

动物动作

Animal 类中的测试方法

【问题讨论】:

  • 您能否定义您是否在谈论何时显式实现所有 接口方法?他们似乎在你的例子中,这使得问题更难回答(尽管帕特里克做得很好)。
  • 这似乎是programmers.stackexchange.com 的一个很好的候选,因为它并不是一个真正的特定编码问题。
  • @SimonWhitehead 好吧,我知道接口的方法需要实现,但是,我的问题是何时使用接口中未定义的类中的其他方法。因为,当我创建像IAnimals ani = new Animal() 这样的对象时,我只能看到 IAnimal 的成员。为了查看Animal 类本身的公共成员,所有实例必须是Animal 类型,如Animal abc = new Animal()
  • 当然——但是你已经在类中显式地实现了接口方法。所以,Animal abc = new Animal(); abc.Move(); 是不可能的。 “显式接口实现”是否是您问题上下文中的参与者肯定会决定我如何回答您的问题。
  • @SimonWhitehead 我会说这是public void TestMethod(),这在这里更令人担忧。为什么我会,在这种情况下,我将访问Animal abc = new Animal(); abc.TestMethod();,而不是将其放入接口中并像IAnimals xyz = new Animal(); xyz.TestMethod(); 一样调用它。我不知道我能不能说得更清楚:-)。

标签: c# oop interface


【解决方案1】:

我的方法是这样的。

一个类的目标应该是拥有一个职责(单一职责原则),并且它的公共契约(即,可公开访问的成员)应该与其履行的职责相关。

我不会尝试在具体的类公共成员和接口公共成员之间建立关联。一个类可能有一个公共成员,以实现与其正在实现的接口契约无关但与实现细节完全相关的横切关注点。或者它甚至可能正在实现多个接口或一些对其职责没有任何意义的接口(例如IDisposable)。

这是否是潜在问题取决于您如何公开此合同。我倾向于公开接口以提供行为,因为它允许我使用 DI 容器等来管理实现配置,这反过来又允许我模拟接口或提供用于单元测试的测试实现。也就是说,如果您正在处理具体类型(这也是有效的“合同”),那么该类型的公开面形成了一个隐含的合同,因此您需要小心更改它(就像您要小心更改接口定义一样)。

我从不特别担心我的类型拥有比接口更多的公共成员,但我确实会尝试注意该类型试图做什么(并注意它何时试图做太多)。

所以我会回答说,最好的做法是审查一个类试图涵盖的职责并尝试将其最小化为一个,但我会说这个公共成员比较不是相关的“代码气味”警报,在我的意见。

【讨论】:

    【解决方案2】:

    接口定义只声明了使实现符合“契约”的属性和方法。

    您几乎永远不会只有在您的类的接口中定义的属性和方法,因为该类通常需要更多的通用协定实现。

    类定义中偏离接口的一个很好的例子是实现ICloneable 的类。您需要实现Clone 方法,但这并没有描述类的实际作用,它只是实现了类与接口的约定。

    【讨论】:

      【解决方案3】:

      在某些情况下,一个类的存在主要是为了满足一个接口;如果一个类的存在是为了实现接口IWuzzler,并且对该类的实例最自然的描述是“a Wuzzler”,那么最好让类的公共面与接口匹配为尽可能好;成员在类中有用的事实表明它可能作为接口的[可能是可选的]部分有用。

      然而,在其他情况下,一个类会为了它自己的目的而存在,但会满足一个接口,这样它就可以被那些不太关心类所做的大部分事情的代码所操作。例如,许多集合类型可能实现IEnumerable<T>,即使它们的主要目的围绕IEnumerable<T> 的大多数消费者一无所知的事物。如果该类实现接口的目的是为了使实例可供外部通用代码使用,那么该类型应该有许多在这些接口中不存在的成员。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-11
        • 2019-11-20
        • 1970-01-01
        • 2013-12-31
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 2021-03-25
        相关资源
        最近更新 更多