![4933701-895cb987d1447fca.png](https://i-blog.csdnimg.cn/blog_migrate/d108b28533c44a02ad76afd7d903a91b.png)
面向对象
面向对象编程最基本的构造是类,一组类构成了编程抽象、模型、模板,通常对应于现实世界的概念。
类
类是现实世界事物的模型
- 事物包括物质(实体)与运动(逻辑)
- 建模是一个去伪存真由表及里的过程
![4933701-1fa02454fac6f4f9.png](https://i-blog.csdnimg.cn/blog_migrate/f36501ce02f918f9f21341be57b690f8.png)
类是一种活动的数据结构,是一个能存储数据并执行代码的数据结构,包含数据成员和函数成员。
![4933701-64ca061f0900bcbe.png](https://i-blog.csdnimg.cn/blog_migrate/57ec7638e0f3a4cbfbe8b89bca08a753.png)
- 数据成员
数据成员存储与类或类的实例相关的数据,数据成员模拟类所表示的现实世界事物的特征。 - 函数成员
函数成员执行代码,模拟类所表示的现实世界的功能和操作。
对象
对象是类的实例,从类创建对象的过程称为实例化(instantiation),因为对象是类的实例(instance)。
声明类并不创建类的实例,而是创建了用于创建实例的模板。
- 对象也叫做实例,是类经过实例化后得到内存中的实体。
- 依照类可创建对象,即实例化。
- 使用 new 操作符创建类的实例
虽然有专门的new操作符分配内存,但没有对应的操作符回收内存。相反,运行时CRL会在对象变得不再由其他活动对象引用时,安排一个时间回收对象占用的内容。如此一来,无需再编译时判断在程序的什么位置回收并归还内存。 - 引用变量与实例的关系
入门
一个运行中的C#程序是一组相互作用的类型对象,它们中的大部分是类的实例。运行中的程序是一组相互作用的对象的集合。
实例:模拟扑克牌游戏
- Dealer 运行游戏
Dealer对象保存纸牌的当前状态和玩家数目等信息,其动作包括发牌和洗牌。 - Player 游戏玩家
Player类保存玩家名称以及押注钱数等信息,并实现如分析玩家当前手上的牌和出牌等动作。
![4933701-bc703741068d42c7.png](https://i-blog.csdnimg.cn/blog_migrate/3718fbf4d6e69c24ef889e0d09a8c763.png)
类的声明
类的声明即定义类,首先要指定关键字class,后跟标识符。
//类的声明:关键字 类名
class MyExcellentClass
{
// 成员声明
}
通过编写类的声明类定义类,类的声明定义了类的特征和成员。
- 类的名称
- 类的成员
- 类的特征
![4933701-ff3a47b6fbf592f5.png](https://i-blog.csdnimg.cn/blog_migrate/7d3bde84f08c9eea912a23e65099a67f.png)
类的声明只是用于创建类的实例的蓝图,一旦类被声明,即可创建类的实例。
- 类是引用类型,意味着类要为数据引用和实际数据都申请内存。
- 数据的引用保存在一个类类型的变量中
要创建类的实例,要从声明一个类类型的变量开始。如果变量没有被初始化则值是未定义的。
![4933701-c7c980f5e83892df.png](https://i-blog.csdnimg.cn/blog_migrate/20146b2d7ecede6a9b091c40ea086ae1.png)
声明类类型的变量所分配的内存是用来保存引用的,而非用来保存类对象实际数据的。要为实际数据分配内存,需使用new运算符。
![4933701-f1a014bacc85b5ae.png](https://i-blog.csdnimg.cn/blog_migrate/19cf09d1ad3280727741274358f1f9ea.png)
- new运算符为任意指定类型的实例分配并初始化内存,依据类型的不同从栈或堆里分配。
- 使用new运算符组成一个对象创建表达式。
- 若内存分配给一个引用类型,则对象创建表达式返回一个引用,指向在堆中被分配并初始化的对象实例。
![4933701-b66e784e3787fa62.png](https://i-blog.csdnimg.cn/blog_migrate/f5ce608aca8f0ccd20ea97c11fe253d7.png)
![4933701-346b196bd7a6f2b9.png](https://i-blog.csdnimg.cn/blog_migrate/e74141e7c100bed52ef3149d46202a59.png)
类成员
字段和方法是最重要的类成员类型,字段是数据成员,方法是函数成员。
- 属性
属性Property存储数据,组合起来表示类或对象当前的状态。 - 方法
方法Method表示类或对象能做什么 - 事件
事件Event为C#特有,类或对象通知其它类或对象的机制。
类成员的侧重点
- 模型类或对象重在属性,如EF。
- 工具类或对象重在方法,如Math、Console。
- 通知类或对象重在事件,如Timer。
字段
- 字段隶属于类的变量
- 字段可以是任何类型
- 字段和变量一样,用来保存数据,具有可读可写的特征。
![4933701-d110dda296c800c6.png](https://i-blog.csdnimg.cn/blog_migrate/2c4920fb4800ea43d1f91a778e8d3f17.png)
面向对象设计的一个核心部分是对数据进行分组,以提供特定结构。在类中存储的变量成为成员变量,更为标准规范的说应该是字段。
实例字段
字段是与包含类型关联的具名存储单元。实例变量是在类的级别上声明的变量,用于存储与对象关联的数据。因此,关联(association)是字段类型和包容类型之间的关联。
class Employee
{
public string FirstName;
public string LastName;
public int Salary = 0;
}
与局部变量声明一样,字段声明包含字段所引用的数据类型。此外,可在声明时赋初始值。
字段不包含static修饰符,意味着它是实例字段。只能从其包容类的实例对象中访问实例字段,无法直接从类中访问。换言之,不创建实例就无法访问。
// 引用变量 = 类的实例
Employee employee = new Employee();
// 访问实例字段
employee.FirstName = "Jun";
employee.LastName = "Chow";
employee.Salary = 52000;
方法
方法是具有名称的可执行代码块,可从程序的不同地方执行。当方法被调用(call/invoke)时,执行自己的代码,返回到调用它的代码并继续执行。
声明方法
- 返回类型 声明方法返回值类型,如无则为void。
- 方法名称
- 参数列表
- 方法体
![4933701-dac0f18f46465e5c.png](https://i-blog.csdnimg.cn/blog_migrate/9a1d9e0d98022a40013209e2db3981cd.png)
实例方法
// 声明类
class Employee
{
// 声明字段
public string FirstName;
public string LastName;
public int Salary = 0;
// 声明方法
public string GetName()
{
// 从包容类内部访问字段
return FirstName + " " + LastName;
}
}
综合案例
using System;
using System.IO;
namespace TestApp
{
class User
{
public int UserID;
public string FirstName;
public string LastName;
public string FullName;
public string CreatedAt = DateTime.Now.ToString("yyyyMMddHHmmssfff");
public void SetID()
{
Random rd = new Random();
this.UserID = rd.Next(100000, 999999);
}
public string GetName()
{
return FirstName + " " + LastName;
}
public void SetName(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
this.FullName = firstName + lastName;
}
public void Save()
{
DataStorage.Store(this);
}
}
class DataStorage
{
public static string DirName = Path.AltDirectorySeparatorChar + DateTime.Now.ToString("yyyyMMdd") + Path.AltDirectorySeparatorChar;
public static void Store(User user)
{
string directory = Directory.GetCurrentDirectory()+DirName;
//Console.WriteLine(directory);
//Console.ReadLine();
//创建目录
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
//写入数据
string filename = directory + user.UserID + ".dat";
FileStream fs = new FileStream(filename, FileMode.Create);
StreamWriter fw = new StreamWriter(fs);
fw.WriteLine(user.FirstName);
fw.WriteLine(user.LastName);
fw.WriteLine(user.FullName);
fw.WriteLine(user.CreatedAt);
fw.Close();
fs.Close();
}
public static User Load(int id)
{
User user = new User();
string directory = Directory.GetCurrentDirectory() + DirName;
string filename = directory + id.ToString() + ".dat";
FileStream fs = new FileStream(filename, FileMode.Open);
StreamReader sr = new StreamReader(fs);
user.FirstName = sr.ReadLine();
user.LastName = sr.ReadLine();
user.FullName = sr.ReadLine();
user.CreatedAt = sr.ReadLine();
sr.Close();
fs.Close();
return user;
}
}
class Program
{
static void Main(string[] args)
{
User user = new User();
user.SetID();
user.SetName("Ali", "baba");
user.Save();
User u = DataStorage.Load(922775);
Console.WriteLine("FirstName = {0}, LastName = {1}, FullName = {2}, CreatedAt = {3}", u.FirstName, u.LastName, u.FullName, u.CreatedAt);
Console.ReadLine();
}
}
}