面向对象和面向过程的区别
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
1. 对象
走路、说话、唱歌;汽车可以启动、加速、减速、刹车、停止等。
在OOP中,对象就是变量和相关的方法的集合。其中变量表明对象的属性,方法表明对象所具有的行为。一个对象的变量构成了这个对象的核心,包围在它外面的方法使这个对象和其他对象分离开来。例如:我们可以把汽车抽象为一个对象,用变量来表示它当前的状态,如速度、油量、型号、所处的位置等,它的行为则为上面提到的加速、刹车、换档等。操作汽车时。不用去考虑汽车内部各个零件如何运作的细节,而只需根据汽车可能的行为使用相应的方法即可。实际上,面向对象的程序设计实现了对象的封装,使我们不必关心对象的行为是如何实现的这样一些细节。通过对对象的封装,实现了模块化和信息隐藏。有利于程序的可移植性和安全性,同时也利于对复杂对象的管理。
简单地说,对象非常类似于本书前面讨论的结构类型。略为复杂的对象可能不包含任何数据,而是只包含函数,表示一个过程。
2.类
在研究对象时主要考虑对象的属性和行为,有些不同的对象会呈现相同或相似的属性和行为,如轿车、卡车、面包车。通常将属性及行为相同或相似对象归为一类。类可以看成是对象的抽象,代表了此类对象所具有的共同属性和行为。典型的类是“人类”,表明人的共同性质。比如我们可以定义一个汽车类来描述所有汽车的共性。通过类定义人们可以实现代码的复用。我们不用去描述每一个对象(如某辆汽车),而是通过创建类(如汽车类)的一个实例来创建该类的一个对象,这样大大碱化了软件的设计。
类是对一组具有相同特征的对象的抽象描述,所有这些对象都是这个类的实例。在C#中,类是一种数据类型,而对象是该类型的变量,变量名即是某个具体对象的标示名。
3.类与对象的区别
a、类是一个抽象的概念,它不存在于现实中的时间/空间里,类只是为所有的对象定义了抽象的属性与行为。就好像“Person(人)”这个类,它虽然可以包含很多个体,但它本身不存在于现实世界上。
b、对象是类的一个具体。它是一个实实在在存在的东西。
c、类是一个静态的概念,类本身不携带任何数据。当没有为类创建任何对象时,类本身不存在于内存空间中。
d、对象是一个动态的概念。每一个对象都存在着有别于其它对象的属于自己的独特的属性和行为。对象的属性可以随着它自己的行为而发生改变
4.属性和字段
通过属性和字段可以访问对象中包含的数据。对象数据可以区分不同的对象,因为同一个类的不同对象可能在属性和字段中存储了不同的值。包含在对象中的不间数据统称为对象的状态。属性是用来修饰字段的。
假定一个对象类表示一杯咖啡,叫做CupOfCoffee。在实例化这个类(即创建这个类的对象)时,必须提供对于类有意义的状态。此时可以使用属性和字段,让代码能通过该对象来设置要使用的咖啡品牌,咖啡中是否加牛奶或方糖,咖啡是否即溶等。给定的咖啡对象就有一个指定的状态,例如“Columbian filter coffee with milk and two sugars”。
可以把信息存储在字段和属性中,作为string变量、int变量等。但是,属性与字段是不同的,属性不能直接访问数据。一般情况下,在访问状态时最好提供属性,而不是字段,因为这样可以更好地控制整个过程,而使用它们的语法是相同的。
对属性的读写访问也可以由对象来明确定义。某些属性是只读的,只能查看它们的值,而不能改变仑们(至少不能直接改变)。还可以有只写的属性,其操作方式类似。
除了对属性的读写访问外,还可以为字段和属性指定另—种访问许可,这种可访问性确定了什么代码可以访问这些成员,它们是可用于所有的代码(公共),还是只能用于类中的代码(私有),或者更复杂的模式。常见的情况是把字段设置为私有,通过公共属性访问它们。
例如,CupOfCoffee类,可以定义5个成员:Type、isInstant、Milk、Sugar、Description等。
5.方法
对象的所有行为都可以用方法来描述,在C#中,方法就是对象中的函数。
方法用于访问对象的功能,与字段和属性—样:方法可以是公共的或私有的,按照需要限制外部代码的访问。它们常常使用对象状态——访问私有成员。例如,CupOfCoffee类定义了一个方法AddSugar()来增加方糖数属性。
实际上,C#中的所有东西都是对象。控制台应用程序中的Main()函数就是类的一个方法。前面介绍的每个变量类型都是一个类。前面使用的每个命令都是一个属性或方法。句点字符“.”把对象实例名和属性或方法名分隔开来。
6.对象的生命周期
每个对象都一个明确定义的生命周期,即从使用类定义开始一直到删除它为止。在对象的生命周期中,除了“正在使用”的正常状态之外,还有两个重要的阶段:
● 构造阶段——对象最初进行实例化的时期。这个初始化过程称为构造阶段,由构造函数完成。
● 析构阶段——在删除一个对象时,常常需要执行一些清理工作,例如释放内存,由析构函数完成。
7.构造函数
所有的对象都有一个默认的构造成数,该函数没有参数,与类本身有相同的名称。一个类定义可以包含几个构造函数,它们有不同的签名,代码可以使用这些签名实例化对象。带有参数的构造函数通常用于给存储在对象中的数据提供初始值。
在C#中,构造函数用new关键字来调用。例如,可以用下面的方式实例化一个CupOfCoffee对象:
CupOfCoffee myCup = new CupOfCoffee();
对象还可以用非默认的构造函数来创建。与默认的构造函数一样,非默认的构造函数与类同名,但它们还带有参数,例如:
CupOfCoffee myCup = new CupOfCoffee(“Blue Mountain”);
构造函数与字段、属性和方法一样,可以是公共或私有的。在类外部的代码不能使用私有构造函数实例化对象,而必须使用公共构造函数。—些类没有公共的构造函数,外部的代码就不可能实例化它们。
8.静态成员
属性、方法和字段等成员是对象实例所特有的,即改变一个对象实例的这些成员不影响其他的实例中的这些成员。除此之外,还有一种静态成员(也称为共享成员),例如静态方法、静态属性或静态字段。静态成员可以在类的实例之间共享,所以它们可以看作是类的全局对象。静态属性和静态字段可以访问独立于任何对象实例的数据,静态方法可以执行与对象类型相关、但不是特定实例的命令,在使用静态成员时,甚至不需要实例化类型的对象。例如,前画使用的Console.WriteLine()方法就是静态的。
9.类成员的修饰符
主要分为protect/private/public三大类。
private:只能被自身的实例方法所使用。
protect:是属于受保护的,外界类不能对其访问,但其子类可以访问。
public:公有的,外部皆可访问。
类的修饰符:
修饰符 |
作用说明 |
new |
新建类,表明隐藏了由基类中继承而来的、与基类中同名的成员 |
public |
公有类,表示外界可以不受限制的访问该类 |
protected |
保护类,表示该类只能被这个类的成员或派生类成员访问 |
internal |
表示该类能够由程序集中的所有文件使用,而不能由程序集以外的对象使用 |
private |
该类只能被这个类的成员访问 |
abstract |
修饰类的时候表示该类为抽象类,不能够创建该类的实例,只能作为基类。 修饰方法的时候表示该方法需要由子类来实现,如果子类没有实现该方法那么子类同样是抽象类;且含有抽象方法的类一定是抽象类 |
sealed |
修饰类时表示该类不能够被继承,修饰方法时表示该方法不能被覆写。 |
Partial:
部分类,可以将一个类分成几部分写在不同文件中,最终编译时将合并成一个文件,且各个部 分不能分散在不同程序集中
static:
修饰类时表示该类时静态类,不能够实例化该类的对象,既然不能实例化该类,那么这个类也就不能够含有对象成员,即该类所有成员为静态;修饰类成员时,该成员为类成员,只能通过【类
.成员名】的方式访问。
当static修饰构造函数时,构造函数不能含有任何参数,不能含有修饰符,构造函数不能对对象成员进行初始化操作。但是能够对静态成员进行初始化或者调用。
不能保证他在什么时候执行,却能保证在第一次使用类型前执行。在静态构造函数中初始化的静态成员为最终初始化结果。
10、类定义的方法:
C#使用class关键字来定义类。其基本结构如下:
Class MyClass
{
// class members
}
这段代码定义了一个类MyClass。定义了一个类后,就可以对该类进行实例化。在默认情况下,类声明为内部的,即只有当前代码才能访问,可以用intemal访问修饰符关键字显式指定,如下所示(但这是不必要的):
internal class MyClass
{
// class members
}
另外,还可以制定类是公共的,可以由其它任意代码访问。为此,需要使用关键字public:
public class MyClass
{
// class members
}
除了这两个访问修饰符关键字外,还可以指定类是抽象的(不能实例化,只能继承,可以有抽象成员)或密封的(sesled,不能继承)。为此,可以使用两个互斥的关键字abstract或sealed。所以,抽象类必须用下述方式声明:
public abstract class MyClass
{
// class members, may be abstract
}
密封类的声明如下所示:
public sealed class MyClass
{
//class members
}
还可以在类定义中指定继承。C#支持类的单一继承,即只能有一个基类,语法如下:
class MyClass : MyBaseClass
{
// class members
}
在C#的类定义中,如果继承了一个抽象类,就必须执行所继承的所有抽象成员(除非派生类也是抽象的)。
编译器不允许派生类的可访问性比其基类更高。也就是说,内部类可以继承于一个公共类,但公共类不能继承于一个内部类。因此,下述代码就是不合法的:
internal class MyBaseClass
{
// class members
}
public class MyClass : MyBaseClass
{
// class members
}
在C#中,类必须派生于另一个类。如果没有指定基类,则被定义的类就继承于基类System.Object。
除了以这种方式指定基类外,还可以指定支持的接口。如果指定了基类,它必须紧跟在冒号的后面,之后才是指定的接口。必须使用逗号分隔基类名(如果有基类)和接口名。
例如,给MyClass添加一接口,如下所示:
class MyClass : IMyInterface
{
// class memebrs
}
所有的接口成员都必须在支持该接口的类中实现,但如果不想使用给定的接口成员,可以提供一个“空”的执行方式(没有函数代码)。
下面的声明是无效的,因为基类MyBaseClass不是继承列表中的第一项:
class MyClass : IMyInterface, MyBaseClass
{
// class members
}
指定基类和接口的正确方式如下:
class : MyBaseClass, ImyInterface
{
// class members
}
可以指定多个接口,所以下面的代码是有效的:
public class MyClass : MyBaseClass, ImyInterface, ImySecondInterface
{
// class members
}