interface i1
{
void add();
}
class abc : i1
{
public void add()
{
Console.WriteLine("hi! add");
}
}
现在在Main
我创建了两个对象,例如:
abc obj1 = new abc();
和
i1 obj2 = new abc();
请告诉我,上述两个实例之间的区别是什么?
答案 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
; subtract
和obj
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”的方法。