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

Gau*_*123 12 c# interface class

我有一个类,CustomerNew和一个接口,ICustomer:

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();
}
Run Code Online (Sandbox Code Playgroud)

我对这两行代码感到很困惑.

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
Run Code Online (Sandbox Code Playgroud)

第一行代码意味着我们正在传递CustomerNew类的对象引用objnew,我是否正确?如果是,那么为什么我不能访问类的方法B()interface objnew

有人可以详细解释这两个.

ang*_*son 28

接口有许多功能和用途,但一个核心问题是能够在商定的合同中向外界提供功能.

让我给你举个例子.考虑一个汽水自动售货机.它有一个或两个插槽供您输入硬币,一些按钮供您选择正确类型的苏打水和一个按钮来分配苏打水(除非选择按钮也这样做).

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

但是,这里是重要的部分,机器内部具有很多功能,它甚至可能有其他按钮和旋钮,通常用于维护人员在出现问题时测试或操作机器,或者他们必须把它倒空或用苏打水填充.

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

你甚至不知道机器在幕后实际运作.我可以创建一个新的自动售货机,从附近的工厂传送苏打水,并将你直接添加的硬币传送到银行,你就不会更聪明了.更不用说我会变得富有,但这是另一个故事.

所以,回到你的代码.

你明确声明objnewICustomer.无论你这个界面背后隐藏什么.您只能访问声明为该接口一部分的任何内容.

另一个变量被声明为具有底层对象的类型,因此您可以完全访问其所有公共功能.可以把它想象成解锁自动售货机并在前面打开时使用它.


hai*_*770 7

在第一行:

ICustomer objnew
Run Code Online (Sandbox Code Playgroud)

您可指示编译器把objnew作为ICustomer而且由于接口不声明B()方法,它的错误.

在第二行:

CustomerNew objCustomerNew
Run Code Online (Sandbox Code Playgroud)

你指的是objCustomerNewas CustomerNew,因为它确实指定了一个B()方法,它编译得很好.

  • @Gaurav123评论不应该是你想要回答的问题的关键部分.这解释了他们问你很好的问题.如果您想要更多详细信息,例如您在评论中包含的内容,那么它应该是您问题的一部分 (3认同)

Mat*_*zer 7

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

由于CustomerNew工具ICustomer的一个实例CustomerNew可以upcastedICustomer.当CustomerNew键入作为ICustomer你只能访问ICustomer成员.

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

更新

OP说:

因此,由于向上转换,我们只能访问界面内部的那些方法,对吗?UPCAST​​ING背后的主要原因是什么?

是.一个简单的解释是一个ICustomer不应强制执行的对象CustomerNew.您需要向下转换ICustomer参考CustomerNew,以便能够访问CustomerNew成员.

由于类和接口都是类型,而C#是强类型语言,因此可以通过提供实际类型来访问对象成员.这就是你需要使用演员表的原因.

例如,您的代码执行隐式upcast:

// This is an implicit cast that's equivalent to
// ICustomer objnew = (ICustomer)new CustomerNew()
ICustomer objnew = new CustomerNew();
Run Code Online (Sandbox Code Playgroud)

隐upcasts是可能的,因为编译器已经知道CustomerNew器具ICustomer反思CustomerNew的元数据,虽然你不能implictly- 垂头丧气一个ICustomer参考,因为谁知道谁实现ICustomer?它可以是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;
Run Code Online (Sandbox Code Playgroud)

如果您不确定ICustomera CustomerNew是否为a ,则可以使用as运算符,如果无法进行强制转换,则不会在运行时抛出异常:

// If asInterface isn't also a CustomerNew, the expression will set null
CustomerNew asClass3 = asInterface as CustomerNew;
Run Code Online (Sandbox Code Playgroud)