创建类和接口的对象有什么区别(参见下面的例子)?

时间:2011-01-23 16:34:12

标签: c# interface

interface i1
{
    void add();
}

class abc : i1
{
    public void add()
    {
        Console.WriteLine("hi! add");
    }
}

现在在Main我创建了两个对象,例如:

abc obj1 = new abc();

i1 obj2 = new abc();

请告诉我,上述两个实例之间的区别是什么?

6 个答案:

答案 0 :(得分:9)

不同之处在于,obj1被输入为abc的实例,而obj2被输入为i1的实例。这两个变量都是对abc实例的引用,但不同之处在于代码中可以访问的内容。假设您有以下内容:

interface IFoo { void Bar(); }
public class Foo : IFoo {
    public void Bar() { Console.WriteLine("Foo.Bar!"); }
    public void Baz() { Console.WriteLine("Baz!"); }
}

然后:

Foo foo = new Foo();
IFoo iFoo = new Foo();

然后以下是合法的:

foo.Baz();

但这不是:

iFoo.Baz(); // compile-time error

关键是编译器不知道iFoo的引用实际上是Foo,因此有一个方法Baz。特别要注意这是可能的:

public class FooFoo : IFoo {
    public void Bar() { Console.WriteLine("FooFoo.Bar!"); }
}

IFoo foofoo = new FooFoo();
foofoo.Baz(); // not legal

请注意,这样做是不合法的,而且很明显为什么。您可以通过类型IFoo的变量调用的唯一方法是在接口中定义的方法,而不管类型IFoo的变量引用的具体类型可能存在的任何方法。

答案 1 :(得分:2)

在您展示的代码中,由于除i1实现之外没有明确的实现和成员,因此没有实际差异。此外,您特别询问实例化中的差异 - 因为您在两种情况下都调用相同的构造函数,所以没有区别。但是,使用不同的代码,可能会有一些显着的差异。

在第一个例子中:

abc obj1 = new abc();

您可以访问以下内容:

  • abc
  • 的公开成员
  • abc的受保护成员,如果在abc
  • 的派生类中调用
  • abc的内部成员,如果在同一程序集中调用
  • abc的私人成员,如果从abc类本身的其他地方调用

您将 无法访问任何明确实现的接口成员。

在第二个例子中:

i1 obj2 = new abc();

您只能访问界面i1

上定义的成员

答案 2 :(得分:1)

接口定义调用者和被调用者之间的契约。实现该接口的任何对象也实现合同。所以你也可以

class cde : i1 { public void add() { console.writeline("cde add!"); } }

然后有一个功能:

void myFunction(i1 adder) { adder.add(); }

的调用如下:

i1 myAbc = new abc();
i1 myCde = new cde();
myFunction(myAbc);
myFunction(myCde);

尽管两个类实现了i1,但它们都实现了相同的契约,因此myFunction可以调用方法。

答案 3 :(得分:1)

在您展示的情况下,对于大多数实际用途没有区别。

但是,假设abc实现了i1以外的其他接口:

interface i1 { void add(); }
interface i2 { void subtract(); }

class abc : i1, i2
{
    public void add() { ... }
    public void subtract() { ... }
}

现在,如果你重复实例化:

abc obj  = new abc();
i1  obj1 = new abc();
i2  obj2 = new abc();

您最终得到三个abc的引用,但这些引用允许您执行不同的操作:

  • 您可以在add;
  • 上同时拨打subtractobj
  • 您可以在add;
  • 上致电obj1
  • 您可以在subtract;
  • 上致电obj2

这是因为接口类型只为您提供了具体类型的“局部视图”。 (虽然这听起来像一个约束,但它实际上是一件好事,因为它允许您明确说明,例如在方法的参数列表中,您希望从该参数中获得什么样的行为或契约;它记录您的内容要求或计划使用该参数。)

答案 4 :(得分:0)

与接口相关的区别在于,如果abc实现除i1之外的任何其他接口(或其他某些方法或公共成员),您将能够为obj1访问它们,但不能在obj2上访问它们。

答案 5 :(得分:0)

最大的区别是obj1只能保存“abc”类型的对象或从中派生的类型,而obj2将能够保存任何实现“i1”的对象。下一个最大的区别是obj1可以传递给期望“abc”或“i1”的方法,而obj2只能传递给期望“i1”的方法。

请注意,虽然obj1和obj2最初都会保存“abc”类型的对象,但这并不意味着它们以后永远不会保留其他对象,这可能是其他类型的对象。因为obj2将被允许保存除“abc”以外的类型的对象,无论它是否实际执行过,编译器都不允许将它传递给需要“abc”的方法。