VB.NET之旅(四)—类和结构

VB.NET之旅(四)—类和结构,第1张

概述  刚上班,就被大李找去了。“Henry,昨天对窗体的 *** 作给你最大的体会是什么?”   “当然有体会,最深的印象就是VB.NET中类是无所不在了,连窗体都成为了一个类。”我深有感触地说。   “没错,类是我们用来构造VB.NET应用程序时的最基本的编程结构了。你也学习过最基本的面向对象编程了,那么你能告诉我,结构与类有什么相似之处与不同之处吗?”   “好的。”我口中回答着,心里还是有点不以为然, 刚上班,就被大李找去了。“Henry,昨天对窗体的 *** 作给你最大的体会是什么?”

  “当然有体会,最深的印象就是VB.NET中类是无所不在了,连窗体都成为了一个类。”我深有感触地说。

  “没错,类是我们用来构造VB.NET应用程序时的最基本的编程结构了。你也学习过最基本的面向对象编程了,那么你能告诉我,结构与类有什么相似之处与不同之处吗?”

  “好的。”我口中回答着,心里还是有点不以为然,“结构和类,都是对成员的封装方式,但是类可以支持继承……”

  大李一边点着头,一边听我说,听到我最后支吾着没了声音才抬起头“还有呢?”

  “没了。”我这时才开始心中发慌。

  “呵呵,相同之处我想你心中还是明白的,它们都含有成员,包括构造函数、方法、属性、字段、常量、枚举和事件。都可以实现接口,都有共享的构造函数。”

  “对不起,最后那一句,都有构造函数是什么意思?结构的构造函数我从来没有自己定义过。”

  大李立刻写下了这一段代码:

@H_301_23@ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
双击代码全选
Structure  SHenry       Public  x, y  As   Integer        Public   Sub   New ( ByVal  x  As   Integer ,  ByVal  y  As   Integer )         Me .x = x         Me .y = y       End   Sub     End   Structure     Sub  main()       Dim  H1  As  SHenry =  New  SHenry()       Dim  H2  As  SHenry =  New  SHenry(2, 1)    End   Sub  

  “真的呢,可以实现结构的构造函数!”我还一直没有注意过这个问题。“可是,你只定义过一个带参数的构造函数,H2的实例化我是明白的,可是H1怎么也能通过编译器检测呢?”其实我心中更想问的是结构怎么也能实例化成对象,那和类真的很象呀。

  “原因么,”大李推了推眼镜,“每个结构都隐式地具有 Public 无参数实例构造函数,该构造函数产生结构的默认值。所以你平时不写构造函数,也一样可以New出一个结构来,对吧?事实上,我们反而在结构类型声明中不可能声明无参数实例构造函数。只能声明‘参数化’实例构造函数。”

  “都可以用new来实例化,结构和类在内存分配上难道也是一样的吗?”这个问题我一直挺不明白,正好借这个话题问一下。

  “在这上面,差别可就大了。”看到大李喜笑颜开的样子,我就知道问到点子上了,立刻摆开架势,作认真倾听状。

  “简单来说,结构是值类型,而类是引用类型。因此,结构使用堆栈分配,类使用堆分配。”

  看到我迷茫的双眼,大李笑了笑,在电脑上飞快地写了个示例:

@H_301_23@ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
双击代码全选
Class  CHenry         Public  z  As   Integer  = 0        ‘能对非静态成员初始化也是一个区别    End   Class     Sub  main()       Dim  H1  As  SHenry =  New  SHenry(0, 2)  '赋给H1.x=0       Dim  H2  As  SHenry = H1      H2.x = 26       Dim  R1  As   New  CHenry()  'R1.z也是等于0       Dim  R2  As  CHenry = R1      R2.z = 26      Console.Writeline( "H1.x="  &H1.x& ",H2.x=" & H2.x)      Console.Writeline( "R1.z= " &R1.z& ",R2.value= " & R2.z)    End   Sub  

  “你看一下结果应该是什么?”大李一边说,一边运行了程序:

@H_301_23@ 1 2 3
双击代码全选
H1.x= 0,  H2.x= 26    R1.z= 26,  R2.value= 26

  大李看着我瞪圆的双眼,慢慢地说:“这就是值类型和引用类型的差别。结构的实例 H2.x 赋值并不影响H1.x,这是因为虽然它们同属于一种SHenry结构,但它们都有各自的存储空间。相反,给 R2.z赋值26后; 则会影响R1 和 R2 都引用的对象”

  “说得更清楚一点,类作为引用类型,是存储在运行时的堆上,只能通过引用该存储来访问它们,不能直接访问。引用类型的变量总是包含该类型的值引用,或包含空引用。空引用不引用任何内容;除分配空引用外,对空引用进行的任何 *** 作都是无效的。引用类型的变量赋值只会创建引用的一个副本,而不是所引用的值的副本。它们实际上都是会指向同一块存储区的。”大李手指了指运行的结果。

  “结构是直接存储在堆栈上,要么在数组中,要么在另一个类型中。当包含结构实例的位置被销毁时,结构实例也会被销毁。值类型总是可以直接访问。我们不能创建对值类型的引用,也不能引用已销毁的值类型实例。值类型的变量总是包含此类型的值。与引用类型不同,值类型的值不能为空引用,也不能引用派生相近程度较大的类型的对象。值类型的变量赋值会创建所赋的值的副本,当然会新开辟一块内存区来保存值。”

  “哦,我明白了。它们还有什么区别没有?”我对结构和类的区别第一次有了深刻的感觉。

  “当然有很多,比如所有的结构成员都默认为 Public,类变量和常量默认为 Private,其他的类成员默认为 Public;结构成员不能声明为 Protected,类成员可以;结构过程不能处理事件,类过程可以;结构变量声明不能指定初始值、New 关键字或数组初始大小,类变量声明可以。”大李喝了口水,停了一下,然后继续说。

  “结构从不终止,所以公共语言运行库从不在任何结构上调用 Finalize 方法;类可由垃圾回收器终止,垃圾回收器会跟踪未完成的引用直到某个特定的实例,当检测到没有剩下的活动引用时,垃圾回收器将在类上调用 Finalize。”

  “这个我可以理解,因为结构是值类型,是由系统统一管理内存,不是引用,所以不会对内存造成危害。”我接着说了两句。

  “还有,你刚才也提到了它们之间一个很重要的区别:结构是不可继承的,而类可以继承。其实结构自身是从 ValueType 类隐式继承下来的。数据类型可分为值类型和引用类型。值类型要么是堆栈分配的,要么是在结构中以内联方式分配的。引用类型是堆分配的。引用类型和值类型都是从最终的基类 Object 派生出来的。当值类型需要充当对象时,就在堆上分配一个包装,该包装能使值类型看上去像引用对象一样,并且将该值类型的值复制给它。该包装被加上标记,以便系统知道它包含一个值类型。这个进程称为装箱,其反向进程称为取消装箱。装箱和取消装箱能够使任何类型像对象一样进行处理。”

  “哦,我明白为什么结构也能被实例化成对象了!”我心中喜不自禁。“类的继承我在用C++和Java时也经常使用,但是VB6是不支持继承的,上次您提到VB.NET可以支持继承了,它是怎么做到的呀!”

总结

以上是内存溢出为你收集整理的VB.NET之旅(四)—类和结构全部内容,希望文章能够帮你解决VB.NET之旅(四)—类和结构所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1290283.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存