CLR via C#(05)- 访问限定、数据成员
今天跟大家分享一下关于访问限定和数据成员的知识。主要包括以下两点:
- Abstract, sealed, virtual, new, override怎么用?
- Const 和 readonly好像都表示不能改变的值,有什么区别呢?
一、 访问限定
类和方法有一些访问限定符,如private,public等。除此之外,还包含一些预定义特性。下面几个你都知道吗?
1. 类的预定义特性
- Abstract——抽象类。不能实例化。如果派生类不是抽象类,则必须实例化。
- Sealed——密封类。不能做基类被继承。
要想既不能实例化又不能被继承? 需要两个步骤:
- seadled修饰。防止被被继承 ;
- 私有化无参构造器。防止实例化自动调用默认无参构造函数。例如:
sealed class Demo
{
private Demo() { }
...
}
2. 方法的预定义特性
- Abstract——用于抽象类中的抽象方法,该方法不能包含具体实现。派生类如果不实现该方法,则必须为抽象类。
public abstract class Animal
{
public abstract void Shout();
}
- Virtual——用于非静态方法。调用时实现的是继承链最末端的方法,也就是按照运行时类型调用的,而不是编译时类型。
- New——隐藏但并不会改变基类中虚方法的实现。(调用的时候,类型是父类时,调用父类的方法;类型是子类时,调用的是子类的方法)
- Override——重写基类中的虚方法。
实例:
public class Animal //基类
{public virtual void Shout() //定义虚方法
{Console.WriteLine("逼我发威啊!"); //虚方法实现
}
}
public class Dog : Animal
{public override void Shout() //override重写基类方法
{Console.WriteLine("汪汪!");
}
}
public class Cat : Animal
{public new void Shout() //new隐藏基类方法
{Console.WriteLine("喵喵~~");
}
}
class Program
{static void Main(string[] args)
{new Animal().Shout(); //“逼我发威啊!”
new Dog().Shout(); //“汪汪!”
new Cat().Shout(); //”喵喵~~”
Console.WriteLine("**************************");
Animal a1 = new Dog();
a1.Shout(); //重写了基类的方法 “汪汪!”
Animal a2 = new Cat();
((Cat)a2).Shout(); //派生类中的方法隐藏了基类的方法 ”喵喵~~”(类型是子类Cat)
a2.Shout(); //基类的方法没有被修改,只是被隐藏 “逼我发威啊!”(类型是父类Animal)
Console.Read();
}
}
二、 数据成员——常量和只读
我们经常提到常量和只读,听上去都是不能改变的意思,那么它们到底有什么区别呢?
1. 常量const
常量是恒定不变的,在编译时就确定了它的值,编译后直接将值存到元数据中。变量类型只能是编译器能直接识别的基元类型,不能是引用类型,因为引用类型需要在运行时调用构造函数进行初始化。
我们给段代码实际看一下:
class TestConst
{
public const int Number = 100; //声明常量并赋值
public string GetName()
{
const string name = "XiaoJing"; //常量用作局部变量
return name;
}
}class Program
{static void Main(string[] args)
{
Console.WriteLine("const:The total number is " + TestConst.Number);
Console.Read();
}
}
通过ILDasm工具查看一下,const变量编译后为static literal类型,所以不难理解,常量是针对类的一部分,而不是实例的一部分。这样它才能保证是恒定不变的。
在使用常量时,编译器从常量模块的元数据中直接取出常量的值,嵌入到IL代码中。所以在声明常量的时候就要为它初始化值。例如上面的例子,Number直接替换为值100。
Main函数的IL代码如下:
还有一点,const常量也可以用于局部变量,例如上面的GetName()方法。
2. 只读字段readonly
类的数据成员通常用来保存一个值类型的实例或者指向引用类型的引用,CLR支持读写和只读两种数据成员,其中只读数据成员使用readonly修饰的。看个实际例子:
class TestReadonly
{
public readonly int Number = 100; //只读实例成员
public TestReadonly()
{
Number = 200; //构造器中重新赋值
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("readonly:The total number is " + new TestReadonly().Number);
Console.Read();
}
}
通过ILDasm.exe工具查看, Readonly实例成员编译后为 initonly修饰。这个例子是只读实例成员,readonly也可以修饰静态只读成员,需要在类静态构造器中初始化,这里就不赘述了。
数据成员是在类的实例构造过程中分配内存的,因此能在运行时刻获取它的值。因此只读成员类型没有限制,可以是基元类型,也可以是引用类型。而且可以在构造器中赋值,声明时赋值与否都可以。
我们查看main函数的IL代码:可以看出首先对TestReadonly类进行实例化,然后读取实例的Number成员的值,是在运行过程中获取值的。
还有要注意的一点,readonly不能用作局部变量,否则编译时就会报错。
最后我们要说明的是,readonly字段不能改变的是引用,而不是字段引用的对象。例如
public sealed class AType
{
public static readonly char[] chars = new char[] { 'a', 'b', 'c' };
}
public sealed class BType
{
public static void Change()
{
AType.chars[0] = 'X';
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(AType.chars[0]);
BType.Change();
Console.WriteLine(AType.chars[0]);
Console.Read();
}
}
运行结果是
a
X
CLR via C#(05)- 访问限定、数据成员的更多相关文章
- 《Effective C#》读书笔记-1.C# 语言习惯-1.使用属性而不是可访问的数据成员
思维导图: 大纲: 1.使用属性而不是可访问的数据成员 属性 指定不同的访问权限 隐式属性降低了声明属性的工作量 允许将数据成员作为公共接口的一部分暴露 ...
- 改善 C# 的语言习惯(一) - 使用属性而不是可访问的数据成员(整理中)
改善 C# 的语言习惯(一) - 使用属性而不是可访问的数据成员 序 为什么我们的程序运行得棒棒的,还要改呢?Why? 答:我们要让程序运行得更快,执行的效率更高,代码的可读性更强,维护的成本更低.. ...
- 《C#高效编程》读书笔记01-使用属性而不是可访问的数据成员
在需求变更中,属性比数据成员更容易修改,例:客户对象不该与空白名称,若你使用公有属性封装Name,那么现在修改一处,而数据成员则可能要修改多处 public class Customer { priv ...
- 3第一周课后练习·阅读计划(2)-使用指针来访问私有数据成员
/* * Copyright (c) 2015, 计算机科学学院,烟台大学 * All rights reserved. * 文件名:test.cpp * 作 靠:刘畅 * 完成日期:2015年 3 ...
- 3第一周课后练习·阅读计划(3)-使用函数来访问私有数据成员
/* * Copyright (c) 2015, 计算机科学学院,烟台大学 * All rights reserved. * 文件名:test.cpp * 作 靠:刘畅 * 完成日期:2015年 3 ...
- C++类中的常数据成员和静态数据成员的区别
刚开始学习C++的类和对象的部分,对类中的常数据成员和静态数据成员的概念和用法经常混淆,所以今天整理一下,顺便说一下,今天是我的生日,祝我生日快乐,呵呵. 常数据成员 常数据成员是指在类中定义的不能修 ...
- C++基础(静态数据成员和静态成员函数)
[简介] 1.静态数据成员在类中声明,在源文件中定义并初始化: 2.静态成员函数没有this指针,只能访问静态数据成员: 3.调用静态成员函数:(1)对象.(2)直接调用: 4.静态成员函数的地址可用 ...
- 【C++】私有数据成员不能用对象去访问吗
首先,必须清楚的是private和public限定的是类而不是对象.因此,在成员函数中访问同类对象的私有成员是完全可以的. 所以,某些教材上所说的“私有数据成员不能用对象去访问”是欠妥当的. 比如,如 ...
- Java中public、private、protect对数据成员或成员函数的访问限制
Java类中对数据成员.成员函数的访问限制修饰有:public.protect.private.friendly(包访问限制) public修饰的数据成员或成员函数是对所有用户开放的,所有用户可以直接 ...
随机推荐
- HDNOIP普及+提高整合
好久没有更新博客了...这几天一直在切 HDNOIP... 正式时跪惨了...所以考完后回来奋力切出了所有题. [COJ3351]HDNOIP201601回文质数 试题描述 回文数是具有对称性的自然数 ...
- 随机添加一个Class,Class提前写好
$("").hover(function(){ var ary = ["red","green","blue",]; v ...
- ExtJs xtype类型介绍
自定义组件在定义的时候可以通过xtype配置为组件指定xtype短名称,此后创建对象可以通过xtype来创建自定义对象了,示例代码如下: Ext.define('MyApp.PressMeButton ...
- Opencv二值图像的分布直方图
Mat img; ]; int main() { VideoCapture video(); if (!video.isOpened()) { ; } Mat img; Mat img1, img2, ...
- vim帮助手册汉化
vim帮助手册汉化 vim帮助手册汉化 下载vimcdoc-1.9.0.tar.gz 安装vimcodc-1.9.0 vim命令模式下输入help可以查看vim的帮助手册.美中不足的是这个帮助手册是英 ...
- 4-python学习——数据操作
4-python学习--数据操作 参考python类型转换.数值操作(收藏) Python基本运算符 数据类型转换: 有时候,可能需要执行的内置类型之间的转换.类型之间的转换,只需使用类名作为函数. ...
- HEOI 2016 游记
闲来无事,把这玩意儿补上. OI生涯中第一次正经的考试.挂的很惨. Day -1 不小心把机油(雾)sm惹毛了. 好像没啥别的事儿. Day 0 说好了上午直接去机房,然而临时说让我们上完前两节课再去 ...
- 17.5---珠玑妙算,四个槽,红色黄色绿色蓝色(CC150)
思路:注意一下,找猜中的时候什么都不用做,直接统计,找伪猜中也是先不管,然后再把结果减去猜中即可. public static int[] calcResult(String a, String b) ...
- Nunit-Writing Tests
Nunit 测试可以被任意支持attributes的.net语言使用 Attributes被用于去标识测试类和测试方法,然后通过不同的方式修改他们的行为 Assertions针对一个或多个约束,测试一 ...
- SQL Server常用命令
1.DECLARE DECLARE命令用于声明一个或多个局部变量.游标变量或表变量. 注:如果定义的变量是字符型,应该指定data_type表达式中其最大长度,否则系统认为其长度为1. declare ...