我创建了这个界面:
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; }
}
此处此代码返回数据并将其强制转换为Phrase:
var phrases = db2.Query<Phrase>("SELECT * FROM Phrase", ans);
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
我想知道的是,我在IPhrase
或Phrase
使用IPhrase
是否有任何区别/优势?在此示例中,我在创建$('#billing_countrycode option[value!="BE"]').remove();
接口时还有什么优势(如果有的话)。这会导致代码更易读吗?
答案 0 :(得分:3)
接口是一个保证的合同,任何实现接口的类都将实现接口中定义的方法和属性。这允许您使用接口创建接受任何实现接口的类的方法,列表等,例如
public interface IExample
{
int GetInt();
}
public void ProcessInt(IExample value)
{
var tempInt = value.GetInt();
// Do processing here
}
这允许将实现接口IExample的任何具体类传递给此方法。该方法确保传递的任何具体类都将实现GetInt方法。
答案 1 :(得分:2)
使用对象可以继承事物:
<强>对象强>
如果您有Animal
个对象,Dog
对象可以继承该对象,因为它是动物。
使用对象继承时,请考虑以下短语: I am a ...._yourObject_...
<强>接口强>
使用界面,您可以将其视为该对象的描述符。例如IWalkOnTwoLegs
或ICanSwim
。
请注意这句话: I can do ...._yourInterface_..
现在回答您的问题,如果您使用的是接口,会不会有所作为?
嗯,在这种情况下不会,但是如果你扩展你的短语并创建一个Question
对象和一个Statement
对象,例如,他们继承自Phrase
,您可以选择返回所有短语(问题和陈述)或仅返回Questions
或仅Statements
的短语。
您还可以将IAmInFrench
和IAmInSpanish
的界面应用于您的词组,这样您就可以拥有扩展的SpanishPhrase
和FrenchPhrase
个对象。
现在你可以返回所有短语,无论是问题,陈述,用不同的语言,或者你可以是具体的,只返回法语阶段。
我发现接口最有用的地方就是统一注册不同类型。
它会产生什么影响:
如果对象上的某个属性不在界面上,那么它肯定会有所不同,那么如果你返回界面,除非你输入类型,否则你将无法轻易访问该属性
例如:
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; }
}
如果退回界面,您将无法访问该属性:
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
var eng = phrases[0].English; //**THIS WONT WORK**
答案 2 :(得分:1)
在本地使用接口和具体对象之间没有区别,如您的示例所示。主要区别在于,您将接口与具体类作为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();
但这种情况再次发生的情况相对较少。对不起愚蠢的Cat&amp;狗的例子!
答案 3 :(得分:0)
类是对象的模板。它本质上是一个蓝图。所以对于一个灯有一个打开和关闭的按钮。假设当您调用此方法时,会将值发送给某个打开和关闭它的控制器。您所要做的就是调用方法开启/关闭,并且中提琴可以正常工作。
界面非常相似。这里可能没有实现开/关方法。你实际上必须去编写代码以打开和关闭灯,但你必须编写开/关方法或它不能是那个接口。假设有一种具有调光功能的新型灯。界面允许您为不同类型的灯实现此新功能。所以它基本上告诉你,你必须完成这些东西(开/关)才能成为一个灯,但我们并不关心你如何实现它。可以为您实现界面的某些部分,但是您必须实现其他部分。
界面什么时候有意义?在这种情况下,您有许多对象在性质上非常相似但在实现上略有不同。例如,假设您有许多类型的形状。每个都将有一个区域。三角形的计算与圆形的计算不同。现在假设您有数百个需要构造的形状,您不会为每种类型的形状制作新对象,您只需实现该接口即可。这使得某人有能力创建形状,甚至是自定义形状,使用类似的方法但不同的实现。
答案 4 :(得分:0)
您的答案取决于您希望使用未来课程的方式。接口是合同,以确保后代类具有接口的所有定义。所以当你想使用多态时,这很有用。通过这种方式,您可以在接口类中定义对象的所有常用规范。接口的另一个优点是您的类可以从多个接口继承,而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
}
}