我在两种情况下都使用过界面。这是我的第一个案例使用界面? 这是我的界面和类
interface IAddition {
int Add();
}
interface IMultiplication {
int Multiplication();
}
这是我的班级
public class Calculation : IAddition, IMultiplication {
int x, y;
public Calculation(int x, int y) {
this.x = x;
this.y = y;
}
public int Add() {
return (x + y);
}
public int Multiplication() {
return (x * y);
}
}
第一种情况是这个
class Program {
static void Main(string[] args) {
Calculation cal = new Calculation(20, 30);
Console.WriteLine("Sum is= " + cal.Add());
Console.WriteLine("Multiplication is= " + cal.Multiplication());
Console.ReadKey();
}
}
第二种情况就是这个
class Program {
static void Main(string[] args) {
Calculation cal = new Calculation(20, 30);
IAddition add = (IAddition)cal;
IMultiplication mul = (IMultiplication)cal;
Console.WriteLine("Sum is= " + add.Add());
Console.WriteLine("Multiplication is= " + mul.Multiplication());
Console.ReadKey();
}
}
这两行的目的是什么?这里铸造的目的是什么?虽然第一种情况具有相同的输出
IAddition add = (IAddition)cal;
IMultiplication mul = (IMultiplication)cal;
答案 0 :(得分:2)
仅第二个案例编程到IAddition
和IMultiplication
接口。即使Calculation
类没有实现IAddition
和IMultiplication
,第一种情况也会有效。
铸造的目的是什么?
请注意,由于您使用显式接口类型声明变量,因此可以安全地删除mul
和add
声明中的强制转换:
IAddition add = cal;
IMultiplication mul = cal;
您还可以使用隐式类型声明重写声明:
var add = (IAddition)cal;
var mul = (IMultiplication)cal;
这两行的目的是什么?
这些行使用Calculation
实现的接口类型声明两个变量。它们在此示例中没有实际区别,但通常您可以使用add
和mul
来具体了解您编程的抽象级别。例如,IAddition add
告诉读者您的程序不需要使用cal
的任何方面,除了这些与添加有关。
答案 1 :(得分:1)
其他答案涵盖了给定的示例代码,但值得添加的是显式接口实现的规则不同。
例如,如果示例类实现如下:
public class Calculation : IAddition, IMultiplication {
int x, y;
public Calculation(int x, int y) {
this.x = x;
this.y = y;
}
public int IAddition.Add() {
return (x + y);
}
public int IMultiplication.Multiplication() {
return (x * y);
}
}
然后需要 。例如:
Calculation cal = new Calculation(10, 10);
cal.Multiplication(); // this will cause a compiler error
((IMultiplication)cal).Multiplication(); // This is the required way to do it
了解更多信息see this article on MSDN
答案 2 :(得分:1)
在这种情况下,目的只是向您展示如何投射类型。它对代码的工作方式没有影响,但是你可以看到,如果你要尝试add.Multiplication()
,编译器就会告诉你这是不允许的。
在这样一个简单的例子中,没有理由像这样强制转换和声明变量。但是,在较大的应用程序中,接口隔离原则有助于我们避免不同代码段的紧密耦合。例如,您可以编写如下方法:
int SumAll(IAddition adder, params int[] values)
{
int sum = 0;
foreach(int n in values)
{
sum = adder.Add(sum, values[i]);
}
return sum;
}
如果您将Calculator
传递给它,上述方法就可以正常工作,但不必使用Calculator
。由于您知道不需要在此方法中乘以任何内容,因此这会将依赖性限制为您实际需要的内容。您可能在将来发现实现具有上限的Add
方法很有用,例如,无论添加多少内容,都不允许数字超过某个数字。将IAddition
对象传递到SumAll
会产生不同的效果,您无需创建不同的SumAll
方法来满足此需求。
Console.WriteLine(SumAll(new Calculator(), 1, 2)); // 3
Console.WriteLine(SumAll(new Calculator(), 1, 2, 3)); // 6
Console.WriteLine(SumAll(new AdderWithMax(4), 1, 2)); // 3
Console.WriteLine(SumAll(new AdderWithMax(4), 1, 2, 3)); // 4
通常,人们发现通过智能地分离接口,他们能够编写更容易测试的代码,并且在将来进行更改时不太可能需要那么多的工作 - 换句话说,更易于维护的代码。
哦,顺便说一下,显式演员表实际上并不是必需的,所以这也会产生同样的效果:
IAddition add = cal;
或:
var add = (IAddition)cal;
答案 3 :(得分:1)
如何使用界面
有许多方式使用接口,从实现到类型检查。
// Definition of interface or sometimes referred to as "Contract"
// Implementing classes must define these methods and properties
public interface IMyInterface
{
void MyMethod();
int MyProperty { get; }
}
// Implementation or sometimes referred to as "Concrete type"
public class MyClass : IMyInterface
{
public void MyMethod();
public int MyProperty { get; set; }
}
// Compile time type checking:
public void MyMethod<T>(T value)
where T : IMyInterface
{ }
// Runtime checking
public void MyMethod(object someobject)
{
var myinterface = someobject as IMyInterface;
if (myinterface != null)
{
//someobject implements IMyInterface so I can do things with it
someobject.MyMethod();
}
}
和铸造的目的?
铸造的目的有很多用途。我将主要演示使用as
关键字,因为它为运行时提供了类型安全性。
您可以使用它来验证类型在运行时实现接口:
public MyMethod(object obj)
{
var calc = obj as ICalc;
if (calc != null)
{
calc.Calculate();
}
}
这可以改进:
public void MyMethod(ICalc calc)
{
calc.Calculate();
}
使用泛型并编译时间类型安全(我认为显示很重要)。
public void MyMethod<TObject>(TObject calc)
where TObject : ICalc
{
calc.Calculate();
}
是我的第一个案例使用界面??
我不确定这意味着什么,我想你想说的是
我是否需要通过投射来使用界面?
不,你不是。让我们来看看这两个类:
public class Calculation1 : IAddition, IMultiplication {
public int Add() { //... ignoring implemenetation
}
public int Multiplication() { //... ignoring implemenetation
}
}
public class Calculation2 {
public int Add() {//... ignoring implemenetation
}
public int Multiplication() {//... ignoring implemenetation
}
}
两个类都实现了相同的方法,因此它们是有效的:
var one = new Calculation1();
one.Add();
var two = new Calculation1();
two.Add();
但是因为第一个实现了接口而第二个没有实现,所以可以将第一个对象传递给不需要知道具体类型的方法。
public void MethodNeedsToAdd(IAddition addCalculator)
{
if (addCalculator != null)
{
addCalculator.Add();
}
}
MethodNeedsToAdd(one); // Valid
MethodNeedsToAdd(two); // Invalid
即使你和我能清楚地看到他们都可以“添加”第二个班级two
没有实现界面。
答案 4 :(得分:0)
一切都是为了隐瞒复杂性。当你这样做时......
IAddition add = (IAddition)cal;
然后,您可以处理此add
项,就好像它可以执行的只是实现您的IAddition
接口一样。如果您正在实施复杂的系统,这可能会很方便。
例如,您可以定义IGetNextItem
接口。然后,您可以选择在从DBMS获取项目的类中实现该接口,而另一个生成随机假项目。您可以投射任一对象,然后将其传递给使用这些项目的软件,而无需告诉消费软件确切地获取项目的实际工作方式。
答案 5 :(得分:0)
你不需要演员。你可以说......
IAddition add = cal;
然而,重点是您正在创建一个实现IAddition接口的任何类型的对象。