C# 非接口方法

C# 非接口方法,c#,oop,interface,abstract-class,C#,Oop,Interface,Abstract Class,我一直在阅读有关接口编程而非实现的书籍。我没有完全理解的一个领域是如何处理非接口方法。例如,接口IAnimal和实现它的Cat类。我的例子是C语言,但我认为它也应该适用于其他语言 public interface IAnimal { void Eat(); } public class Cat : IAnimal { public Cat() public void Eat() { //Do something

我一直在阅读有关接口编程而非实现的书籍。我没有完全理解的一个领域是如何处理非接口方法。例如,接口IAnimal和实现它的Cat类。我的例子是C语言,但我认为它也应该适用于其他语言

public interface IAnimal
{
    void Eat();

}

    public class Cat : IAnimal
    {

    public Cat()

    public void Eat()
    { 
         //Do something
    }


    public string Meow()
    {
        return "meow";
    }

}
据我所知,我似乎应该尝试使用接口,而不是cat实现,例如

Main()
{
    IAnimal cat = new Cat();
}
但这使我无法访问我的meow方法,因为它不是IAnimal接口的一部分。我是否应该创建另一个实现IAnimals的接口ICat,并让Cat实现它?这是否意味着所有方法都应该是来自接口或抽象类的实现?或者我在这里做错了什么


感谢您的帮助。

如果您需要访问该方法,则需要进行显式转换

在这种情况下,对于其他可能实现它的类,让Meow()方法更通用会更有趣:

public interface IAnimal
{
    void Eat();
    void Speak();
}

public class Cat : IAnimal
{  
    public void Eat() {  }

    public string Speak()
    {
        return "meow";
    }   
}

public class Dog : IAnimal
{  
    public void Eat() {  }

    public string Speak()
    {
        return "au";
    }   
}

你要做的是,你要有另一个界面,代表说英语的动物,或者从IAnimal继承,或者将其添加为第二个界面。具有会说话的动物的类实现第二个接口

public interface IAnimal
{
    void Eat();
}

public interface ISpeakingAnimal : IAnimal
{
    string Speak();
}

public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    public string Speak()
    {
        return "meow";
    }
}

public class Fish : IAnimal 
{
    public Fish()

    public void Eat()
    { 
         //Do something
    }
}
public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    string ISpeakingAnimal.Speak()
    {
        return Meow();
    }

    public string Meow()
    {
        return "meow";
    }
}
使用继承的接口

public interface IAnimal
{
    void Eat();
}

public interface ISpeakingAnimal : IAnimal
{
    string Speak();
}

public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    public string Speak()
    {
        return "meow";
    }
}

public class Fish : IAnimal 
{
    public Fish()

    public void Eat()
    { 
         //Do something
    }
}
public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    string ISpeakingAnimal.Speak()
    {
        return Meow();
    }

    public string Meow()
    {
        return "meow";
    }
}
具有第二个装饰器接口

public interface IAnimal
{
    void Eat();
}

public interface ISpeakable
{
    string Speak();
}

public class Cat : IAnimal, ISpeakable
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }

    public string Speak()
    {
        return "meow";
    }
}

public class Fish : IAnimal 
{
    public Fish()

    public void Eat()
    { 
         //Do something
    }
}
如果需要的方法不是
Speak()
,而是
Meow()
,则可以使用显式接口实现仅通过该接口公开
Speak()
方法

public interface IAnimal
{
    void Eat();
}

public interface ISpeakingAnimal : IAnimal
{
    string Speak();
}

public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    public string Speak()
    {
        return "meow";
    }
}

public class Fish : IAnimal 
{
    public Fish()

    public void Eat()
    { 
         //Do something
    }
}
public class Cat : ISpeakingAnimal 
{
    public Cat()

    public void Eat()
    { 
         //Do something
    }


    string ISpeakingAnimal.Speak()
    {
        return Meow();
    }

    public string Meow()
    {
        return "meow";
    }
}

接口的要点是定义实现该接口的类的通用行为。您正确地注意到,对cat的定义如下:

    IAnimal cat = new Cat();
使您无法访问不在IAnimal中的Cat类中的方法。那么,为什么鼓励它以这种方式实施呢

答案很简单:它使以后更改代码变得非常容易。例如,如果我们有一个实现IAnimal的Dog类,如下所示:

    public class Dog : IAnimal
    {
        // some methods
    }
    Cat cat = new Cat();
然后,我们可以很容易地将Cat类替换为Dog类,而无需更改任何其他代码。换言之,我们可以取代:

    IAnimal cat = new Cat();

无需更改整个程序中的任何其他代码(除了变量名)。这是因为根据IAnimal定义Cat和Dog会迫使它们只使用IAnimal中的方法,尽管它们在Cat和Dog中的实现方式可能不同

当然,如果您只想使用特定于猫或狗的东西,您必须显式地定义类,正如@Erick在他的回答中提到的,如下所示:

    public class Dog : IAnimal
    {
        // some methods
    }
    Cat cat = new Cat();

通常,您应该尝试在接口中定义尽可能多的常见行为,仅在绝对必要时显式地强制转换到特定类,如Cat或Dog。这使您的代码更加通用和多变。

我在这个主题上的两点是,您确实需要依赖抽象(即接口)而不是实现

顺便说一句,这不是太过分了吗?不需要为对象模型中的任何类定义接口。如果需要接受满足给定契约的某些对象,通常需要定义接口

例如,我不会定义
IAnimal
ICat
接口。可能我会定义一个抽象类
Animal
,而只定义一个具体类
Cat

如果出于某种原因,我需要在某个API中接受可以吃东西的生物,我会定义如下接口:

public interface IFeedable
{
      void Feed(Food food);
}
如果一个活着的人能说话:

除非没有动物独有的特性/属性/行为,否则我将保留这些接口

如果你需要在某个地方制作一个对话对象:

ITalkative talkative = some as ITalkative;

if(talkative != null)
{
    talkative.Talk();
}
或者,如果需要向对象馈送:

IFeedable feedable = some as IFeedable;

if(feedable != null)
{
    feedable.Feed(new Vegetable());
}

正如您所看到的,您并没有为所有内容定义接口,只是为需要在某些API中处理的内容定义接口,您不关心谁可以执行某些操作和/或拥有某些数据,但是您只关心对象可以分别执行或公开某些行为和数据。

您能为接口添加一个更通用的方法吗?
string speak()
。?然后,无论哪个类实现它,都可以有自己的消息。对于根本不会说话的类fish呢?那么它可以返回一个空字符串。或者没有声音的指示器。或者会说话的动物可以实现
ITalkingAnimal
。因此,从评论中可以看出,您主张在相关接口中包含所有方法,而不是像示例中那样保留任何方法。对于何时实现多个接口与链接接口?取决于您计划如何使用它。作为你问题中的例子,你可以使用interitance。如果你有像
IEnumerable makethespeak(IEnumerable obj)
这样的代码,你可能会使用
ISpeakable
,所以如果你有可以说话但动物不能使用的东西(例如,你可能也有一个
IRobot
),然后确认你是说所有的方法都应该在某个地方的接口上实现?你遵循一种模式,在某些地方它是有意义的,在某些地方它是没有意义的。例如,如果DTO对象具有属性,但没有方法,那么为其提供接口就没有意义。