相关概念
1. this关键字
类的非静态方法中存在一个关键字this ,它用于引用访问该方法的当前实例。 形参与实例成员同名须恢复this 引用
2. 重载构造函数
构造函数可以对类对象进行初始化,类的构造函数也可以重载。
3. 内存回收与析构函数
为避免资源泄露,C#的公共语言运行环境(CLR)进行自动的内存管理,采用垃圾回收机制释放对象不再学要的内存空间。该机制通过调用析构函数来完成。 在默认情况下,编译器自动生成空的析构函数。 一个类中只能有一个析构函数; 构造函数和析构函数不能继承或重载; 析构函数没有参数和返回类型; 构造函数和析构函数都是由系统自动调用的,发生早创建对象和销毁对象时;
4. 对象初始化器
对象初始化器是利用属性为其对象的实例成员初始化。 在创建对象的语句中,使用一堆大括号完成,其中每个初始化操作都是一个赋值操作,左边是一个属性名,右边则是具体要赋的值。 使用对象初始化器特别适用于没有构造函数的情形。 在类Time中添加3个属性,每个属性都包含get访问器和set访问器:
5. 数据抽象与封装
类是对数据和方法的封装,封装把类的属性和方法看成了一个密不可分的整体,从而使类具有明确的独立性,这样能够完成整地描述并对应于一类具体的事物,封装是面向对象程序设计的基本特征之一。 类的封装对于类的使用者隐藏了实现的细节,这种描述类的功能而不管其实现细节称为数据抽象。 面向对象编程的主要活动就是生成自己的新的数据类型(即类)和表达这些数据之间的相互作用。
6. readonly实例变量
类中使用const 可以定义不能修改其值得实例变量(常量),该类的各个对象都使用。 如果要在类中定义这样的变量,其值在构造函数中进行初始化,初始化后就不能修改 ,但不同的对象调用构造函数时可以将该变量初始化成不同的值,这样的变量可以用readonly 关键字进行修饰。 例如下面的语句:
private readonly in INCREMENT;
代码例程
例子1:对象初始化器使用
namespace Ch07Ex01
{
class Program
{
static void Main ( string [ ] args)
{
Time2 t1 = new Time2 { Hour = 3 , Minute = 5 , Second = 6 } ;
Console. WriteLine ( t1) ;
}
}
public class Time2
{
private int hour;
private int minute;
private int second;
public int Hour
{
get { return hour; }
set { hour = ( value >= 0 && value < 24 ) ? value : 0 ; }
}
public int Minute
{
get { return minute; }
set { minute = ( value >= 0 && value < 60 ) ? value : 0 ; }
}
public int Second
{
get { return second; }
set { second = ( value >= 0 && value < 60 ) ? value : 0 ; }
}
public override string ToString ( )
{
return string . Format ( "{0:D2}:{1:D2}:{2:D2}" , hour, minute, second) ;
}
}
}
例子2:职工档案管理系统
一个类中的成员也可以是其他类的对象,这个功能称为合成 ,合成也是软件复用的一种方式。
namespace Ch07Ex03
{
class Program
{
static void Main ( string [ ] args)
{
Date birthdate = new Date ( 1980 , 5 , 3 ) ;
Date workdate = new Date ( 1999 , 7 , 20 ) ;
Employee Emp1 = new Employee ( "销售处" , "张工" , birthdate, Position. ENGINEER, workdate) ;
Emp1. SetSalary ( 3000 , 2000 , 1000 , 50 , 20 ) ;
Emp1. ShowMessage ( ) ;
birthdate. init ( 1979 , 4 , 8 ) ;
workdate. init ( 2002 , 3 , 1 ) ;
Employee Emp2 = new Employee ( "项目部" , "李工" , birthdate, Position. MANAGER, workdate) ;
Emp2. SetSalary ( 2000 , 2900 , 1500 , 50 , 20 ) ;
Emp2. ShowMessage ( ) ;
}
}
class EmpSalary
{
public float Wage;
public float Subsidy;
public float Rent;
public float CostOfElec;
public float CostOfWater;
public float RealSum
{
get { return Wage + Subsidy - Rent - CostOfElec - CostOfWater; }
}
}
public enum Position
{
MANAGER,
ENGINEER,
EMPLYEE,
WORKER
}
class Date
{
int day, month, year;
public Date ( int yy, int mm, int dd)
{
init ( yy, mm, dd) ;
}
public Date ( Date x)
{
init ( x. year, x. month, x. day) ;
}
public void init ( int yy, int mm, int dd)
{
year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900 ;
month = ( mm >= 1 && mm <= 12 ) ? mm : 1 ;
day = ( dd > 1 && dd <= 31 ) ? dd : 1 ;
}
public void Printymd ( )
{
Console. WriteLine ( "{0}-{1}-{2}" , year, month, day) ;
}
}
class Employee
{
string Department;
string Name;
Date Birthdate;
Position EmpPosition;
Date DateOfWork;
EmpSalary Salary = new EmpSalary ( ) ;
public Employee ( string Depart, string Name, Date tBirthdate, Position nPosition, Date tDateOfWork)
{
this . Department = Depart;
this . Name = Name;
this . Birthdate = tBirthdate;
this . EmpPosition = nPosition;
this . DateOfWork = tDateOfWork;
}
public void SetSalary ( float wage, float subsidy, float rent, float elec, float water)
{
Salary. Wage = wage;
Salary. Subsidy = subsidy;
Salary. Rent = rent;
Salary. CostOfElec = elec;
Salary. CostOfWater = water;
}
public float GetSalary
{
get { return Salary. RealSum; }
}
public void ShowMessage ( )
{
Console. WriteLine ( "部门:{0}" , Department) ;
Console. WriteLine ( "姓名:{0}" , Name) ;
Console. WriteLine ( "出生日期:" ) ;
Birthdate. Printymd ( ) ;
Console. WriteLine ( "职务:" ) ;
switch ( EmpPosition)
{
case Position. MANAGER: Console. WriteLine ( "经理" ) ; break ;
case Position. ENGINEER: Console. WriteLine ( "工程师" ) ; break ;
case Position. EMPLYEE: Console. WriteLine ( "职员" ) ; break ;
case Position. WORKER: Console. WriteLine ( "工人" ) ; break ;
}
Console. Write ( "工作日期:" ) ;
DateOfWork. Printymd ( ) ;
Console. WriteLine ( "工资:{0}" , GetSalary) ;
Console. WriteLine ( "------------------------------------" ) ;
}
}
}
例子3:Time类
namespace Ch07Ex02
{
class Program
{
static void Main ( string [ ] args)
{
Time t1 = new Time ( ) ;
t1. Show ( ) ;
Time t2 = new Time ( 2 , 34 , 34 ) ;
t2. Show ( ) ;
}
}
public class Time
{
private int hour;
private int minute;
private int second;
public void Show ( )
{
Console. WriteLine ( "{0:D2}:{1:D2}:{2:D2}" , hour, minute, second) ;
}
public Time ( )
{
hour = minute = second = 0 ;
Console. WriteLine ( "Default" ) ;
}
public Time ( int h, int m, int s)
{
hour = h >= 0 && h <= 24 ? h : 0 ;
minute = m >= 0 && m <= 59 ? m : 0 ;
second = s >= 0 && s <= 59 ? s : 0 ;
Console. WriteLine ( "struct2" ) ;
}
~ Time ( )
{
Console. WriteLine ( "Destroy" ) ;
}
}
}
例子4:点与直线
namespace Ch07Ex01
{
class Program
{
static void Main ( string [ ] args)
{
Line line1 = new Line ( ) ;
Console. WriteLine ( "Distance line1:{0}" , line1. Distance ( ) ) ;
Line line2 = new Line ( 1 , 1 , 4 , 5 ) ;
Console. WriteLine ( "Distance line2:{0}" , line2. Distance ( ) ) ;
Point p1 = new Point ( 1 , 1 ) ;
Point p2 = new Point ( 4 , 5 ) ;
Line line3 = new Line ( p1, p2) ;
Console. WriteLine ( "Distance line3:{0}" , line3. Distance ( ) ) ;
}
}
class Point
{
public double X { get ; set ; }
public double Y { get ; set ; }
public Point ( )
{
X = Y = 0 ;
}
public Point ( double x, double y)
{
X = x;
Y = y;
}
}
class Line
{
private Point p1;
private Point p2;
public Line ( )
{
p1 = new Point ( ) ;
p2 = new Point ( ) ;
}
public Line ( double x1, double y1, double x2, double y2)
{
p1 = new Point ( x1, y1) ;
p2 = new Point ( x2, y2) ;
}
public Line ( Point p1, Point p2)
{
this . p1 = p1;
this . p2 = p2;
}
public double Distance ( )
{
return Math. Sqrt ( ( p1. X - p2. X) * ( p1. X - p2. X) + ( p1. Y - p2. Y) * ( p1. Y - p2. Y) ) ;
}
}
}