C#中类 类型的变量是通常所说的“对象么?”类的实例又是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huzhikuizainali
V2EX    C#

C#中类 类型的变量是通常所说的“对象么?”类的实例又是什么?

  •  
  •   huzhikuizainali 2023-1009 04:48:34 +08:00 1551 次点击
    这是一个创建于 732 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我面向对象的知识来自于 matlab ,比较简单。比如你定义了一个 class A ,那么你实例化一个对象就用 a=A(); 就可以了(假设类 A 的构造函数允许参数为空) 但是到了 C#,我发现比较复杂。请看下面的截图。给出了一个 “类 类型的变量” 概念。请问这个变量是通常说的“对象”么? 和“类的实例” 是一回事么? 因为这段文字中没有给出“类的实例”的明确定义( matlab 中对象和类的实例是一回事)

     截图 

    之所以纠结这个问题,是因为下面的情况是在 matlab 面向对象程序中从未遇到的情况。mgr 到底是哪个类的对象呢? IExtensionManager 的? FileExtensionManage ? 虽然 FileExtensionManage 是 IExtensionManager 的子类 ,但是二者的字段 数量可能都不一样,最后 mgr 到底以谁为模板生成对象了呢?会不会出现鼠头鸭脖的矛盾呢?

     截图 

    image

    cxe2v
        1
    cxe2v  
       2023-10-09 08:43:55 +08:00
    mgr 是 FileExtensionManage 的实例,IExtensionManager 是接口,定义了一堆未实现的方法,FileExtensionManage 通过:这个符号继承了 IExtensionManager 内的方法定义,具体实现是在 FileExtensionManage 这个 class 里
    huntagain2008
        2
    huntagain2008  
       2023-10-09 11:45:04 +08:00
    我作为小白的回答如下:
    > mgr 到底是哪个类的对象呢? IExtensionManager 的? FileExtensionManage ?
    mgr 当然是 FileExtensionManage 的对象。

    > 虽然 FileExtensionManage 是 IExtensionManager 的子类 ,但是二者的字段 数量可能都不一样,最后 mgr 到底以谁为模板生成对象了呢?会不会出现鼠头鸭脖的矛盾呢?

    子类这个说法应该不对。': IExtensionManager'只是实现这个接口,并不是子类。
    mgr 声明的变量类型是 IExtensionManager ,对象依然是 FileExtensionManage 为模版生成的。
    不会有什么矛盾,只是增加 IsValid(fileName)的方法。
    Jax6
        3
    Jax6  
       2023-10-09 16:15:15 +08:00
    这里有一个是基类或接口的概念,可以说 FileExtensionManage 类继承了 IExtensionManager 接口,mgr 是 FileExtensionManage 的实例对象,即可以调用 IExtensionManager 中抽象的在 FileExtensionManage 中真实实现业务的接口。是更细一级的概念。这个就像 C#中类都是派生于基类 object 一样。相当于一个大纲,继承则会在保持原有大纲的情况下进行内容的丰富。同理,你也可以把你的 FileExtensionManage 类赋值给 obj,也是没问题的。
    object i = new FileExtensionManage();
    huzhikuizainali
        4
    huzhikuizainali  
    OP
       2023-10-09 17:32:45 +08:00
    @Jax6 谢谢回复
    我看了一下 C#接口的介绍,结合了类 类型的变量的概念。产生了 两个派生问题:

    1 、语法层面的问题 假设要实例化一个“纯”A 类的对象,C#中的语法往往是 A a= new A() ; , matlab 中只需要 a= A() ; 。我觉得 C#中 a 前面那个 A 很多余啊。难道不能在用户不特别声明的情况下默认 a= new A();就是实例化一个“纯” A 类的对象么?

    2 、“非纯”A 类的情况。我在 matlab 中学过抽象类,也知道抽象类的好处和价值。但是在 Matlab 中只接触过如下思路,假设 A 是抽象类,B 和 C 是继承了 A 的具体类。然后 b= B(); c=C();就可以了,比如 B 类是法师 C 类是射手,那么就可以实现 b.attack c.attack 多态下的不同攻击方法。但是我无法理解 A b=new B() ; A c= new C(); 这个 A 在这里的作用。难道是告诉编译器对象 b 和对象 c 是 接口 A 下面的 子类的对象么?完全没必要啊,因为 public class B:A 已经阐述了这种继承关系。
    其次 A b=new B(); 和 B b= new B(); 有什么不同呢?
    Zhuzhuchenyan
        5
    Zhuzhuchenyan  
       2023-10-09 20:30:22 +08:00   1
    1. C#的语法允许使用 var 关键词来自动推断类型,例如 A a = new A()可以写成 var a = new A()
    2. 这个问题算是比较常见的了

    2.1 A b=new B(); 和 B b= new B(); 有什么不同呢?
    相同点:同样都是调用 B 的构造方法,b 同样都是 Class B 的实例
    不同点:A b=new B();这样的方式下无法调用派生类 B 的方法,只能调用基类 A 的方法

    2.2 存在这样的方式主要是有的时候我们只关心基类而不关心派生类,单独使用确实比较奇怪,这里更多是想向你阐述这样的一种转换方式是合法的。

    其他的使用方式,比如说,B 是法师,C 是射手,基类 A 中有个方法 Attack(A target),接受一个 A 类型的对象并攻击他,那么就可以这样使用
    var b = new B()
    var c = new C()
    b.Attack(c) // 合法,此处形参中将 c 隐式转换为 A 了
    huzhikuizainali
        6
    huzhikuizainali  
    OP
       2023-10-09 23:50:57 +08:00
    @Zhuzhuchenyan 谢谢谢谢回复
    1.如你所说,确实如此
    2.1 如果想实现“ A b=new B();这样的方式下无法调用派生类 B 的方法,只能调用基类 A 的方法”。要实现这个目的,完全可以将 B 类中相关方法设为私有,这样选择权在类的设计者手中,且更灵活。所以 C#允许 A b=new B()是否还有其他深意?特别是 c#中有 A 类 类型的变量 b 这种概念,在 Matlab 中 b 就是对象。不会叫作变量。我不知道这是翻译习惯的问题?还是二者概念确实不同?
    huntagain2008
        7
    huntagain2008  
       2023-10-11 14:35:19 +08:00
    小白我的理解
    > C#允许 A b = new B()是否还有其他深意?
    如#3 所说,是更细一级的概念。我问了下 ChatGPT ,它告诉我:
    在 C#中,当我们使用 object 或 IExtensionManager 来声明一个变量时,该变量将被视为对象的基类,因此只能调用基类中定义的方法和属性。而无法直接调用派生类中特有的方法和属性。

    至于深意,ChatGPT 的回答是:
    1. 多态性:通过将变量声明为基类类型,我们可以在运行时将其赋值为不同的派生类的实例。这样做的好处是,可以使用相同代码来处理不同类型的对象,实现代码的可扩展性和灵活性。通过多态性,可以通过基类类型的变量来处理不同派生类的对象,提高代码的可重用性和可维护性。
    2. 封装性:将变量声明为基类类型有助于实现封装性,即隐藏派生类的具体实现细节。将对象的具体类型和实现细节封装起来,而只暴露基类的公共接口。这样做可以实现代码的模块化和解耦,提高代码的可维护性和可扩展性。

    > c#中有 A 类 类型的变量 b 这种概念,在 Matlab 中 b 就是对象。不会叫作变量。我不知道这是翻译习惯的问题?还是二者概念确实不同?

    我的理解是首先变量的定义是在高级程序设计语言允许使用描述性的名字指向主存储器中的位置,而不必再使用数字地址,这样的名字称为变量。那么,一般的变量指的都是基本数据类型,比如整型、布尔型、字符型等。但是,教科书也提到像 GIF 、JPEG 和 HTML 这样的类型可能也要像整型和浮点型一样通用。而面向对象范型使程序员可以在一门程序设计语言提供的的原语类型的基础之上扩展可用数据类型的指令系统,这种能力是面向对象范型的一个著名的特征,所以这不是翻译习惯,就是变量,只是声明的一个类类型的变量。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1152 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 23:28 PVG 07:28 LAX 16:28 JFK 19:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86