【C#与.NET程序设计】(4)- C#类及OOP
来源:互联网 发布:国密 java 编辑:程序博客网 时间:2024/06/06 17:59
类
类的串联构造函数
考虑如下构造函数重载
// 构造函数的重载class Motorcycle{ public int driverIntensity; public string driverName; // 默认构造函数 public Motorcycle(){} // 冗余的构造函数 public Motorcycle(int intensity) { if(intensity > 10) intensity = 10; driverIntensity = intensity; } public Motorcycle(int intensity, string name) { if(intensity > 10) intensity = 10; driverIntensity = intensity; driverName = name; }}
其中 intensity 的验证代码是冗余的:
- 一种方法是创建一个函数专门负责 intensity 的验证
- 另一种更好的方法是使用串联构造函数链
class Motorcycle{ public int driverIntensity; public string driverName; // 构造函数链 public Motorcycle(){} public Motorcycle(int intensity):this(intensity, "") {} public Motorcycle(string name):this(0, name) {} // 主构造函数 public Motorcycle(int intensity, string name) { if(intensity > 10) intensity = 10; driverIntensity = intensity; driverName = name; }}
调用流程:
类比构造函数参数列表,首先进入主构造函数(包含所有参数),然后才进构造函数链中特定构造函数
此外,.NET4.0 平台还支持可选参数的方法创建构造函数
// 可选参数的单个构造函数// 仅 .NET4 平台支持class Motorcycle{ public int driverIntensity; public string driverName; public Motorcycle(int intensity = 0, string name = “”) { if(intensity > 10) intensity = 10; driverIntensity = intensity; driverName = name; }}
类的static关键字
类(或结构)可以通过 static 定义静态成员
- 类内的静态函数和静态变量不是通过类实例调用
- 静态成员只能操作静态数据或调用类的静态方法
- 类内的静态变量只会初始化一次,类的不同实例共享同一个静态变量
// 静态方法不通过类实例调用// 如Console类的 WriteLine() 方法Console.WriteLine("i am static"); // 正确Console c = new Console(); // 错误c.WriteLine("its wrong");
静态成员的初始化
- 直接在变量声明时赋值
- 使用静态构造函数赋值
// 不管创建多少个对象,确保静态数据只被分配一次// 声明时初始化class SavingAccount{ public double currBalance; public static double currInterestRate = 0.04;}// 使用静态构造函数// 针对静态变量需要在运行时获取(比如数据库或外部文件)的情况class SavingAccount{ public double currBalance; public static double currInterestRate; static SavingAccount() { currInterestRate = 0.04; }}
静态构造函数的注意点:
- 一个类只可以定义一个静态构造函数(不允许重载)
- 静态构造函数不允许访问修饰符,不接受任何参数
- 无论创建了多少对象,静态构造函数只执行一次
静态类
// 静态类static class TimeUtilClass{ public static void PrintTime() {...} public static void PrintDate() {...}}
- 静态类只能包含静态成员
- 不能使用 new 创建静态类,直接用就好(TimeUtilClass.PrintDate();)
OOP
OOP的三个核心:封装、继承、多态
- 封装:隐藏一个对象的内部实现并保护数据完整性
- 继承:如何促进代码重用
通过继承(”is-a”关系),子类可以继承基类核心的功能,并扩展基类的行为
“has-a”关系:一个类定义另一个类的成员变量 - 多态:如何用同样的方式处理相关对象
基类定义抽象(abstract)/虚拟(virtual)方法,派生类重写该方法以实现多态
访问修饰符
- 默认类型成员是 private 的;类型是 internal 的
- class 只能用 public 或 internal 修饰
使用 .NET 属性进行封装
- 产品级代码类成员尽量为 private ,外部通过类方法读取和修改成员
- .NET提倡使用属性来强制数据封装
// 利用 属性 实现强制封装class Employee{ //字段数据 private string empName; //属性 public string Name { get{return empName;} set { if(value.Length > 15) Console.WriteLine("Invalid name"); else empName = value } }}// 直接调用Name来实现读写Employee emp = new Employee();emp.Name = "Marv";Console.WriteLine("Employee is named: {0}", emp.Name);
- Name 这个属性直接跟empName挂钩(两者类型一致都是 string)
- 通过实现 set 和 get 方法完成 private 变量的读写
- value 总是表示调用者设置的值,value类型与属性本身类型一致
- 构造函数中通过使用类属性来初始化变量
// 使用 Name 属性更新构造函数public Employee(string name){ Name = name;}
- 不要再定义 set_Name() 和 get_Name() 方法,因为编译器会将 set 和 get 解释为 set_ 和 get_,会导致混淆
- set 和 get 默认是 public的,可以用修饰符改变其可见性,也可以设为 只读/只写
// set/get 可见性// 仅当前类及其派生类成员可以赋值public string SocialSecurityNumber{ get{return empSSN;} protected set{empSSN = value;}}// 只读// 不实现 set 就可以了public string SocialSecurityNumber{ get{return empSSN;}}// 只写// 不实现 get 就可以了public string SocialSecurityNumber{ set{empSSN = value;}}
- 自动属性
对于包含多个变量的类,挨个实现 get 和 set 是很麻烦的
如果没有其他额外操作(比如赋值检查),仅仅是读/写,可以使用自动属性
// 自动属性// 自动属性不允许只读/只写设定class Car{ public string PetName{get; set;} // get 和 set 必须写全,无法设定只读/只写 // 等价于 private string carName; public string PetName { get {return carName;} set {carName = value;} }}
对象初始化器
在实际中,类构造函数往往无法初始化所有数据
对象初始化器可以只用少量代码实现数据初始化
// 对象初始化器class Rectangle{ private Point topLeft = new Point(); private Point bottomRight = new Point(); public Point TopLeft { get {return topLeft;} set {topLeft = value;} } public Point BottomRight { get {return bottomRight;} set {bottomRight = value;} }}// 传统的初始化方法Rectangle r = new Rectangle();Point p1 = new Point();p1.X = 10;p1.Y = 10;r.TopLeft = p1;Point p2 = new Point();p2.X = 20;p2.Y = 20;r.BottomRight = p2;// 对象初始化器技术// 调用默认构造函数Rectangle r = new Rectangle{TopLeft = new Point{X = 10, Y=10}, BottomRight = new Point{X=200, Y=200}};
常量数据和只读字段
// 常量数据// 定义后不能修改class mathClass{ public const double PI = 3.14;}// 常量数据默认是 静态,所以调用方式为mathClass.PI;//*******************************// 只读字段// 与常量数据的不同是:1.可以在构造函数中赋值(运行时决定值)// 2. 默认不是静态class mathClass{ public readonly double PI = 3.14; // 或者 public readonly double PI; public mathClass() { PI = 3.14; }}
分部类型
一般来说一个类一个.cs文件,对于比较复杂的类,可以用分部类型 partial 将类的实现切分到多个 .cs 文件
// 分部类型// 编译器会将两个文件的内容合并到一起// employee_1.cspartial class Employee{}// employee_2.cspartial class Employee{}
参考
【1】C#与.NET 4高级程序设计(第5版)
阅读全文
0 0
- 【C#与.NET程序设计】(4)- C#类及OOP
- 【C#与.NET程序设计】(5)- C#OOP
- C# OOP程序设计目录
- 【C#与.NET程序设计】(1)- .NET
- 【C#与.NET程序设计】(2)- C#基本数据类型及控制结构
- 【C#与.NET程序设计】(6)- C#垃圾回收及接口类型
- 【C#与.NET程序设计】(3)- C#基本参数类型
- 【C#与.NET程序设计】(7)- C#泛型、委托
- 【C#与.NET程序设计】(8)- C#事件、Lambda
- C#与.NET.3.5高级程序设计(第4版) 读后感
- C#与.NET 4高级程序设计:第5版
- [连载]C#程序设计(01)--- .NET概述
- C#与.NET 3.0高级程序设计(特别版)问题与错误列表
- C#与.NET 3.0高级程序设计(特别版)问题与错误列表
- 《C#与.NET 3.5高级程序设计(第4版)》有奖书评征集活动
- C#与.NET 3.5高级程序设计(第4版)这本书怎么样
- C#讲座(3)--面向对象的程序设计-oop在C#中的应用
- C#中的OOP概念
- 从经济学博士到爬坑机器学习十年,微软首席数据科学家谢梁的AI故事
- 委托的学习以及使用
- 笔记:关于hibernate在dao层要导入的包
- 史上最简单的react脚手架搭建
- linux 环境下JDK的安装+环境变量配置
- 【C#与.NET程序设计】(4)- C#类及OOP
- POI使用案例02---向excel中写入数据
- OPENCV3+VS2015配置教程
- 蒙特卡洛算法简单理解与demo
- 我的第一个实验
- 栈与堆栈的区别
- EmailUtils--QQ
- 如何解决高并发下缓存被击穿的问题
- Python help