技术的基础知识
面向对象的基本概念
面向对象是一种程序设计方法,其基本思想是使用对象,类,继承,封装等进行程序设计,
根本目的是建立更加健壮,稳定,可维护的软件系统。面向对象的设计方法从现实世界中客观存在的事物出发构造软件系统,在系统构造中尽可能运用人类的自然思维方式。
类:
类是用来描述具有相同行为和属性的实体,是构成系统的基本单位,从更加抽象的角度讲,
类是先生世界中事物的一个抽象,它反映了该事物在系统中需要保存和发挥的作用;
它是一组属性和有权对这些属性进行操作的一组服务的封装体;客观世界是由类(对象)和类(对象)之间的联系组成的。
封装性:
封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:
◇
把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。
◇
信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。
封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的
"
交叉感染
"
,使软件错误能够局部化,大大减少查错和排错的难度。
多态性
对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或服务在一般类及其各个特殊类中具有不同的语义。例如:
"
几何图形
"
的
"
绘图
"
方法,
"
椭圆
"
和
"
多边形
"
都是
"
几何图
"
的子类,其
"
绘图
"
方法功能不同。
编译时多态
,有时也叫
先期联编(
early binding),
在编译时就能够确定类的成员方法被调用。方法重载就是实现了编译时多态..
运行时多态,有时也叫
滞后联编(late binding), 系统在运行时,根据其实际类型确定调用类的成员方法。抽象类和接口专门用来实现
运行时多态.
C#中几个容易遗忘的概念
接口:
接口就是约定,一个接口定义一个协定,实现接口的类或结构必须遵守其协定。
我们首先来看一个比较简单的例子:
// keyword_interface.cs
// Interface implementation
using System;
interface IPoint
{
// Property signatures:
int x
{
get;
set;
}
int y
{
get;
set;
}
}
class MyPoint : IPoint
{
// Fields:
private int myX;
private int myY;
// Constructor:
public MyPoint(int x, int y)
{
myX = x;
myY = y;
}
// Property implementation:
public int x
{
get
{
return myX;
}
set
{
myX = value;
}
}
public int y
{
get
{
return myY;
}
set
{
myY = value;
}
}
}
class MainClass
{
private static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.x, p.y);
}
public static void Main()
{
MyPoint p = new MyPoint(2,3);
Console.Write("My Point: ");
PrintPoint(p);
}
}
输出
My Point: x=2, y=3
我们再看一个在系统使用的例子,你也可以petshop 3.0 , petshop 4.0中大量看到这种结构
见文件夹下面
Interfaceex
项目
运行结果:
输入
1
出现结果:
Now, CalculateWages in TestService1
1000
输入
2
出现结果
Now, CalculateWages in TestService2
2000
输入0
退出系统
分析下里面的代码:
首先在项目Iservice
中定义接口:
using System;
namespace IService
{
public interface IEmployee
{
///
/// 计算工资
///
double CalculateWages();
}
}
其次在项目TestService1
中实现接口:
using System;
using IService;
namespace TestService1
{
///
/// 具体实现
///
public class Employee:IEmployee
{
public Employee()
{
}
public double CalculateWages()
{
Console.WriteLine("Now, CalculateWages in TestService1");
double Wages=0;
//经过计算 write code
Wages=1000;
return Wages;
}
}
}
在项目TestService2
中实现接口
using System;
using IService;
namespace TestService2
{
///
/// 具体实现
///
public class Employee:IEmployee
{
public Employee()
{
}
public double CalculateWages()
{
Console.WriteLine("Now, CalculateWages in TestService2");
double Wages=0;
//经过计算 write code
Wages=2000;
return Wages;
}
}
}
在项目ServiceFactory
中根据名称选择具体实现的接口的类
using System;
using IService;
using System.Reflection;
namespace ServiceFactory
{
///
/// 选择具体的程序集
///
public class ServiceEmployee
{
public static IService.IEmployee Create(string Path)
{
string className=Path+".Employee";
//是重要的技术,利用了反射,具体实现动态加载程序集
return (IService.IEmployee)Assembly.Load(Path).CreateInstance(className);
}
}
}
在Interfaceex
中的调用:
string strPath=Console.ReadLine();
while(strPath!="0")
{
if(strPath=="1"||strPath=="2")
{
string Path=ConfigurationSettings.AppSettings[strPath];
IService.IEmployee Employer=ServiceFactory.ServiceEmployee.Create(Path);
Console.WriteLine(Employer.CalculateWages().ToString());
}
strPath=Console.ReadLine();
}
这样做的好处:
1 调用和具体实现的分离,可以根据方便地进行分层开发,
2
结构清晰,维护性好 当某天需求发生变化时,可以新增项目TestService3实现Iservice接口的类,通过配制项目Interfaceex的App.config文件,就可以实现需要变化而不修改Interfaceex中的任何代码
接口和抽象类区别
用abstract声明的类是一个抽象类,(来自msdn)::
- 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。
- 如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
- 如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。
- 如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。
就自己的使用经验而言 接口不包含任何成员的实现而抽象类可以提供成员的实现是他们的最大区别。
反射(在运行时了解类型信息)
反射是指在运行时创建类型实例,然后调用和访问这些实例
当然通过反射命名空间中的类以及 System.Type,您可以获取有关已加载的
程序集和在其中定义的类型(如
类、
接口和
值类型)的信息
如果你有兴趣具体见:
NET 动态加载程序集 (一)
动态加栽程序集(二)
动态加载程序集(三)