Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OOPS概念:将对象引用传递给接口和在C#中创建类对象有什么区别?_C#_Class_Interface - Fatal编程技术网

OOPS概念:将对象引用传递给接口和在C#中创建类对象有什么区别?

OOPS概念:将对象引用传递给接口和在C#中创建类对象有什么区别?,c#,class,interface,C#,Class,Interface,我有一个类,CustomerNew,还有一个接口,iccustomer: public class CustomerNew : ICustomer { public void A() { MessageBox.Show("Class method"); } void ICustomer.A() { MessageBox.Show("Interface method"); } public void B(

我有一个类,
CustomerNew
,还有一个接口,
iccustomer

public class CustomerNew : ICustomer
{
    public void A()
    {
        MessageBox.Show("Class method");
    }

    void ICustomer.A()
    {
        MessageBox.Show("Interface method");
    }


    public void B()
    {
        MessageBox.Show("Class Method");
    }
}

public interface ICustomer
{
    void A();
}
我对这两行代码感到非常困惑

ICustomer objnew = new CustomerNew();
CustomerNew objCustomerNew = new CustomerNew();
objnew.B(); // Why this is wrong?
objCustomerNew.B(); // This is correct because we are using object of class
第一行代码表示我们在
objnew
中传递CustomerNew类的对象引用,对吗?如果是,那么为什么我不能使用
接口objnew
访问类的方法B()

有人能详细解释一下这两个问题吗。

在第一行:

ICustomer objnew
您正在指示编译器将
objnew
视为
iccustomer
,并且由于接口未声明
B()
方法,因此它会出错

在第二行:

CustomerNew objCustomerNew

您将
objCustomerNew
称为
CustomerNew
,因为它确实指定了
B()
方法,所以它可以很好地编译。

接口有许多特性和用法,但一个核心问题是能够在约定的合同中向外部世界展示功能

让我给你举个例子。考虑一下自动贩卖机。它有一两个插槽供您输入硬币,几个按钮供您选择正确类型的苏打水,还有一个按钮供您分配苏打水(除非选择按钮也这样做)

现在,这是一个接口。这隐藏了界面背后的机器复杂性,并为您提供了一些选择

但是,这里是重要的一部分,机器内部有很多功能,甚至可能有其他按钮和旋钮,通常在出现故障时,或者当维修人员不得不清空机器或将其装满苏打水时,维修人员可以测试或操作机器

机器的这一部分对您是隐藏的,您只能访问添加到该接口的外部接口的创建者

你甚至不知道机器在幕后是如何运作的。我可以创建一个新的自动售货机,将苏打水从附近的工厂传送进来,并将您添加的硬币直接传送到银行,这样您就不会更聪明了。更不用说我会很富有,但那是另一回事了

那么,回到你的代码

您明确地将
objnew
声明为
iccustomer
。你在这个界面后面放的任何东西都是隐藏的。您只能访问作为该接口一部分声明的任何内容


另一个变量被声明为具有基础对象的类型,因此您可以完全访问它的所有公共功能。可以把它想象成打开自动售货机的锁,在正面打开的情况下使用它。

实际上,接口也是一种类型(你不能创建接口实例,因为它们只是元数据)

由于
CustomerNew
实现了
iccustomer
,因此可以将
CustomerNew
的实例升级到
iccustomer
。当
iccustomer
被键入为
iccustomer
时,您只能访问
iccustomer
成员

这是因为C#是一种强类型语言,因此,为了访问特定成员(即方法、属性、事件…),您需要一个对象引用,该引用由定义要访问的成员的类型限定(即,您需要将
CustomerNew
对象存储在
CustomerNew
类型的引用中,以访问方法
B

更新 OP说:

因此,由于向上转换,我们只能访问内部的方法 界面,对吗?向上投射是这背后的主要原因

是的。一个简单的解释是,实现
iccustomer
的对象不应强制为
CustomerNew
。您需要向下转换
iccustomer
CustomerNew
的引用,以便能够访问
CustomerNew
成员

由于类和接口都是类型,而C#是强类型语言,因此可以通过提供对象的实际类型来访问对象成员。这就是为什么需要使用类型转换

例如,您的代码执行隐式向上转换:

// This is an implicit cast that's equivalent to
// ICustomer objnew = (ICustomer)new CustomerNew()
ICustomer objnew = new CustomerNew();
隐式向上转换是可能的,因为编译器已经知道
CustomerNew
实现
iccustomer
内省
CustomerNew
元数据,而您不能隐式向下转换
iccustomer
引用,因为谁知道谁实现了
iccustomer
?它可以是
CustomerNew
或任何其他类或结构:

ICustomer asInterface = new CustomerNew();

// ERROR: This won't compile, you need to provide an EXPLICIT DOWNCAST
CustomerNew asClass1 = asInterface;

// OK. You're telling the compiler you know that asInterface
// reference is guaranteed to be a CustomerNew too!
CustomerNew asClass2 = (CustomerNew)asInterface;
如果您不确定
iccustomer
是否为
CustomerNew
,可以使用
as
操作符,如果无法进行强制转换,该操作符在运行时不会引发异常:

// If asInterface isn't also a CustomerNew, the expression will set null
CustomerNew asClass3 = asInterface as CustomerNew;

您的
objnew
变量是对实现
iccustomer
的对象的引用。请注意,这可能是任何对象,只要它实现
iccustomer
。因此此引用公开的所有内容都是iccustomer的成员,而iccustomer只是方法
a()
在您的示例中

如果您确实希望访问对象的
B()
方法,该对象由
objnew
引用,则必须将其显式转换为
CustomerNew
引用(这是C#的工作安全类型),例如:

CustomerNew objCustomerNew = objnew as CustomerNew;
objCustomerNew.B();


请记住,
objnew
可以是实现
iccustomer
的任何类型,因此如果以后实现其他
iccustomer
类,则转换
objnew为CustomerNew
可以解析为
null

这与编译时间有关(即静态)类型检查。如果你看这两行

ICustomer objnew = new CustomerNew();
objnew.B(); 
您可以清楚地看到,
objnew
引用的对象有一个
B()
方法,因此您知道第二行在运行时不会有问题

但是,编译器并不是这样看待它的
ICustomer objnew = new CustomerNew();
objnew.B(); 
ICustomer objnew = new CustomerNew();
if( some complicated expression ) objnew = new CustomerOld() ;
objnew.B(); 
void f( ICustomer objnew ) {
    objnew.B(); 
}
public interface IMyInterface
{

}

public class MyBaseClass:IMyInterface
{
    public string B()
    {
        return "In Abstract";
    }
}

public class MyDerivedClass : MyBaseClass
{

}
        MyBaseClass inst = new MyDerivedClass();
        inst.B(); //Works fine 

        MyDerivedClass inst1 = new MyDerivedClass();
        inst1.B(); //Works fine

        IMyInterface inst2 = new MyDerivedClass();
        inst2.B(); //Compile time error