如何使用界面和铸造目的?

时间:2015-09-17 15:53:06

标签: c#

我在两种情况下都使用过界面。这是我的第一个案例使用界面? 这是我的界面和类

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;

6 个答案:

答案 0 :(得分:2)

仅第二个案例编程到IAdditionIMultiplication接口。即使Calculation类没有实现IAdditionIMultiplication,第一种情况也会有效。

  

铸造的目的是什么?

请注意,由于您使用显式接口类型声明变量,因此可以安全地删除muladd声明中的强制转换:

IAddition add = cal;
IMultiplication mul = cal;

您还可以使用隐式类型声明重写声明:

var add = (IAddition)cal;
var mul = (IMultiplication)cal;
  

这两行的目的是什么?

这些行使用Calculation实现的接口类型声明两个变量。它们在此示例中没有实际区别,但通常您可以使用addmul来具体了解您编程的抽象级别。例如,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接口的任何类型的对象