当我输入对象时,使用接口和类有什么区别吗?

本文关键字:什么 区别 接口 输入 对象 | 更新日期: 2023-09-27 18:14:15

我创建了这个接口:

public interface IPhrase
{
    int CategoryId { get; set; }
    string PhraseId { get; set; }
    string English { get; set; }
    string Romaji { get; set; }
    string Kana { get; set; }
    string Kanji { get; set; }
}

和这个类:

public class Phrase : IPhrase
{
    public Phrase()
    {
    }
    public int CategoryId { get; set; }
    public string PhraseId { get; set; }
    public string English { get; set; }
    public string Romaji { get; set; }
    public string Kana { get; set; }
    public string Kanji { get; set; }
}

这里的代码返回数据并将其类型转换为短语:

var phrases = db2.Query<Phrase>("SELECT * FROM Phrase", ans);
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);

我想知道的是,我在这里使用IPhrasePhrase是否有任何区别/优势?在这个例子中,我创建一个IPhrase接口有什么优点(如果有的话)。这会导致代码更可读吗?

当我输入对象时,使用接口和类有什么区别吗?

接口是一个契约,它保证任何实现接口的类都将实现接口中定义的方法和属性。这允许你使用接口来创建方法、列表等,这些方法和列表接受任何实现该接口的类,例如

public interface IExample
{
    int GetInt();
}
public void ProcessInt(IExample value)
{
    var tempInt = value.GetInt();
    // Do processing here
}

这允许任何实现接口IExample的具体类被传递给这个方法。该方法确保传递的任何具体类都将实现GetInt方法。

对于可以继承的对象:

如果你有一个Animal对象,Dog对象可以从它继承,因为它是一个动物。

对于对象继承,考虑这个短语: I am a ...._yourObject_...

界面

对于接口,您可以将其视为该对象的描述符。如IWalkOnTwoLegsICanSwim

想想这个短语: I can do ...._yourInterface_..

现在回答你的问题,是否使用接口会有区别吗?

好吧,在这种情况下它不会,但是如果你扩展你的短语并创建一个Question对象和一个Statement对象,例如,它们继承自Phrase,你可以选择返回所有的短语(问题和陈述),或者只返回QuestionsStatements的短语。

你也可以应用一个接口说IAmInFrenchIAmInSpanish到你的短语,这样你就可以扩展SpanishPhraseFrenchPhrase对象。现在,您可以返回所有的短语,无论它们是不同语言的问题、陈述,或者您可以指定并只返回法语阶段。

我发现接口最有用的地方是在unity中注册不同类型。

如果对象上有一个不在接口上的属性,那么如果你返回接口,你将无法很容易地访问该属性,除非你进行类型强制转换。

,

public class Phrase : IPhrase
{
    public Phrase()
    {
    }
    public int CategoryId { get; set; }
    public string PhraseId { get; set; }
    public string English { get; set; }
}

和接口

public interface IPhrase
    {
      int CategoryId { get; set; }
    }

如果您返回接口

,则无法访问属性English:
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
var eng = phrases[0].English; //**THIS WONT WORK**

在本地使用接口和具体对象之间没有区别,就像在您的示例中一样。主要的区别是当你发送接口和具体类作为api参数或构造函数参数时,最好使用接口,这样你就可以实现解耦和可测试性。

对于你的问题,简短的答案是否定的,没有区别,无论你想使用接口还是具体对象作为局部变量是你自己的选择(对你来说似乎更容易读懂)。不要忘记,字段和属性最好声明为接口,这样可以提供更大的灵活性。

使用具体对象而不是局部接口时需要考虑的最后一件事是,您可能希望有一天更改为您提供该对象的方法的签名,以返回实现相同接口的另一种对象,在这种情况下,您也应该更改局部变量(即使它不是那么糟糕,我不得不注意到它很少发生),如以下示例:

interface IAnimal
{
    void Run();
}
class Cat : IAnimal
{
    public void Run()
    {
        //...
    }
}
class Dog : IAnimal
{
    public void Run()
    {
        //...
    }
}

如果在你的代码中你有一个返回Cat的方法,你使用:

Cat GetAnimal()
{
    return new Cat();
}
Cat myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();  

然后,如果您更改GetAnimal签名以返回Dog,您的代码应该更改以便编译为:

Dog myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();  

但是如果你使用的是接口,那么当方法的签名被更改时,你的代码需要更改的机会就会减少:

IAnimal myAnimal = GetAnimal(); //this is working whether a Cat or a Dog is received.
myAnimal.Run(); 

但这种情况相对较少发生。为这只笨猫感到抱歉。狗的例子!

类是对象的模板。它本质上是一个蓝图。这里的灯有一个开关。当你调用这个方法的时候一个值被发送到某个控制器去打开和关闭它。你所要做的就是调用on/off方法,然后它就可以工作了。

接口非常相似。这里可能没有实现on/off方法。实际上,你必须编写代码来打开和关闭灯,但你必须编写开/关方法,否则它就不能是那个接口。假设有一种新型的具有调光功能的灯。接口允许您为不同类型的光实现这个新功能。它基本上是在告诉你,你必须完成这些东西(开/关)才能让它成为一盏灯,但我们不关心你如何实现它。接口的某些部分可以为您实现,但其他部分必须由您实现。

什么时候接口才有意义?在这种情况下,您有许多本质上非常相似但在实现上略有不同的对象。例如,假设你有很多种形状。每个都有一个面积。三角形和圆形的计算是不同的。现在假设你有数百个需要构造的形状,你不需要为每种形状创建新对象,你只需要实现接口。这赋予某人创建形状的能力,甚至是自定义形状,方法相似但实现不同。

你的答案取决于你想如何使用你未来的类。接口是确保后代类具有接口所有定义的契约。当你想要使用多态性时,这是很有用的。通过这种方式,您可以在接口类中定义对象的所有通用规范。接口的另一个优点是,你的类可以从多个接口继承,这是c#中其他类型的类所不允许的。下面是一个示例代码。希望对你有帮助:

public interface IShape
{
    float Area { get; }
    float circumference { get; }
}
public class Rectangle : IShape
{
    private float l, h;
    public Rectangle( float length, float height ) { l = length; h = height; }
    public float Area { get { return l * h; } }
    public float circumference { get { return ( l + h ) * 2; } }
}
public class Circle : IShape
{
    private float r;
    public Circle( float radius ) { r = radius; }
    public float Area { get { return (float)Math.PI * r * r; } }
    public float circumference { get { return (float)Math.PI * r * 2; } }
}
public class SomeClass
{
    IShape[] shapes = new IShape[] // Can store all shapes regardless of its type
    {
        new Rectangle( 10f, 20f ),
        new Rectangle( 15f, 20f ),
        new Rectangle( 11.6f, .8f ),
        new Circle( 11f ),
        new Circle( 4.7f )
    };
    public void PrintAreas()
    {
        foreach ( var sh in shapes )
            Console.WriteLine( sh.Area ); // prints area of shape regardless of its type
    }
    public void PrintCircumference(IShape shape )
    {
        Console.WriteLine( shape.circumference ); // again its not important what is your shape, you cant use this function to print its cicumference
    }
}