1.面向对象程序设计概述
1.面向过程程序设计的来由
要解释面向对象程序设计,都应当将其与面向过程程序设计作对比。
面向过程程序设计往往是流程化的,以机械式思维来解决问题,同时要求程序员的思维模式偏向硬件,从机械的角度来考虑如何一步步解决问题。
然而随着计算机科学、网络以及信息技术的发展,这种编程思维越发力不从心。这意味着在开发大型软件项目时,面向过程程序设计往往显得力不从心,程序员不得不开发一个个模块来完成功能,代码复用率低下、研发周期长、软件工作效率低下等等。
因此为了适应现代社会对软件开发的更高需求,面向对象程序设计作为解决方案而兴起。
面向对象的核心思想为万物皆对象。这种思想十分接近于人类思维方式,而不像面向过程程序设计那样程序员不得不从机器的角度来思考问题。
同时面向对象导入了类与对象的思想。类就是特定拥有共同属性、特征的对象的集合,对象则是类的实例,它实现了类的属性、特征等等。这和现实世界中是非常贴近的,比如鸟可以作为一种类,而乌鸦和喜鹊都可以作为鸟类的对象,他们共同拥有鸟类的属性——翅膀、飞翔等等。然而它们之间却也有不同的属性,比如乌鸦拥有全黑的羽毛,而喜鹊却不是,这就涉及到继承与子类了。
由此,面向对象程序设计产生并且不断发展壮大,成为或不可缺的一部分。
1.典型的面向对象语言
Java/c#/Python等等。众多编程语言或者设计之初已支持面向对象特性,又或者后来在更新面向对象特性。而如今在高等编程中,掌握面向对象特性已经或不可缺,编程语言对于面向对象的支持度又决定了其性能。
1.面向对象编程语言的展望
从目前来看,作为程序员必须掌握一门面向对象编程语言,同时IT界技术不断发展,类似于F#、Docker等技术不断涌出,以及互联网的风靡,不少程序员更加青睐于类似于javascript、java、python等对网络支持性良好的语言,然而这一切都脱离不了面向对象思想,因为万物皆对象。
2.面向对象特征
1.继承
在面向对象程序设计中有个重要概念——继承不得不提。同时其存在也极为增加了代码可重用性,简化了软件开发过程。
被继承的类成为父类、基类,继承的类成为子类、派生类。子类可以继承拥有权限的父类的变量、方法、访问器等等,然而在其基础上扩展类的定义。子类还可以重写和覆盖父类的方法,而这也是面向对象的多态性的体现。
首先由继承就可知存在访问修饰符,它们分别为internal、public、protected、private。
public:访问不受限制。
protected:访问仅限于包含类或从包含类派生的类型。
Internal:访问仅限于当前程序集。
protected internal:访问仅限于当前程序集或从包含类派生的类型。
private:访问仅限于包含类型。
其中还有特殊的两类:sealed和virtual。
Sealed所修饰的类无法作为基类被继承。
Virtual可用于修饰需要被重写的方法等等。
接下来用一些C#示例来说明继承特性。
namespace temp
{
class animalClass
{
public class animal
{
public int number;
int Number
{
set { this.number = value; }
get { return this.number; }
}
public animal(int num)
{
this.number = num;
Console.WriteLine("Create animal");
}
public void animfun()
{
Console.WriteLine("Function of animal");
Console.WriteLine("Number of animal is {0}", number);
}
virtual public void virtualfun()
{
Console.WriteLine("Don't do it!");
}
}
public class bird:animal
{
public string colour;
string Colour
{
set { this.colour = value; }
get { return this.colour; }
}
public bird(int num,string col):base(num)
{
this.colour=col;
}
public void birdfun()
{
Console.WriteLine("Function of bird");
Console.WriteLine("number of bird is {0} and colour of bird is {1}", number, colour);
}
public override void virtualfun()
{
Console.WriteLine("Change it!");
}
}
}
}
以上为animal和bird的定义。
namespace temp
{
class Program
{
static void Main(string[] args)
{
animalClass.bird bir = new animalClass.bird(19, "blue");
bir.birdfun();
}
}
}
如上实例化bird类的对象bir之后在调用birdfun可得结果:
Create animal
Function of bird
number of bird is 19 and colour of bird is blue
可见bird类的确继承了来自animal类的number字段并且拥有了自己的属性——用于储存colcur的字符串。同时可以调用animal类的animfun函数和bird类的birdfun函数。
2.抽象
面向对象程序设计用经常涉及子类继承父类,就如乌鸦是鸟类的一个对象一样,鸟类抽象出了乌鸦和喜鹊共同的属性。同时由此我们可以引入面向对象中的另一个概念——抽象。
1.接口
在C#中接口就是抽象的一种,它可以要求继承自其的类必须实现其中的方法,提供一种统一的标准来实现类。
namespace temp
{
public interface Interface1
{
void fun();
}
}
示例中定义一个名为Interface1的接口,其中它要求实现无返回值的fun方法。
namespace temp
{
class fromInterface1 :Interface1
{
public void fun()
{
Console.WriteLine("This is fun");
}
}
}
类fromInterface1则继承自Interface1,因此倘若不实现fun方法,编译器就会报错。如:error CS0535: “temp.fromInterface1”不实现接口成员“temp.Interface1.fun()”。
2.抽象类
C#中抽象还有另一种实现方式——抽象类以及抽象方法。
namespace temp
{
class @abstract
{
abstract class num1
{
abstract public void fun();
}
class num2 : num1
{
public override void fun()
{
Console.WriteLine("Do it!");
}
}
}
}
同继承自抽象接口,子类继承抽象类中的抽象方法时,必须重写抽象方法,否则编译器会报错,无法通过编译。
同时抽象类也有着其特征,不能从抽象类实例化对象,同时子类也必须实现抽象类中所有抽象方法。如同示例中所示范,用关键词override来重写抽象方法。
3.多态
多态是一种面向对象程序设计中的概念。多态为程序设计提供了灵活性、变通性与多样性。
在C#中多态可以体现为函数重载、抽象类、重写函数。
1.函数重载:
定义了如下类:
class simpleSample
{
public simpleSample(int n)
{
Console.WriteLine("Create simpleSample and this is 1");
}
public simpleSample(int n,int m)
{
Console.WriteLine("Create simpleSample and this is 2");
}
}
当以语句simpleSample sam = new simpleSample(1)实例化时,输出Create simpleSample and this is 1
当以语句simpleSample sam = new simpleSample(1,2)实例化时,输出Create simpleSample and this is 2
可见相同的函数,当调用时传入参数不同时,可以完成不同的功能,这就是函数重载。
2.抽象类。
重写函数在抽象一节中已经出现示例。只有用virtual、abstract、override定义的函数才能重写。通过重写函数、继承抽象类,可以以相同的函数、形式完成不同的功能,这就是多态的本质之一。
多态为面向对象程序设计重要特性之一,也即同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
4.封装
封装的定义为隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读取和修改的访问级别。
1.属性
在C#中可以用属性对进行封装。属性可以分为get和set访问器,由此可以将字段设置为可读、可写或可读写,同时不仅如此,还可在访问器中进行操作来完成需求。
定义如下:
class simpleSample2
{
public int number;
public int Number
{
get{return this.number;}
set { this.number = value; }
}
public int number2;
public int Number2
{
set { this.number2 = value + 1; }
get {return this.number2;}
}
public simpleSample2()
{
Console.WriteLine("Create simpleSample2");
}
}
主程序如下:
simpleSample2 sam = new simpleSample2();
sam.Number = 1;
sam.Number2 = 1;
Console.WriteLine("number={0} and number2={1}", sam.number, sam.number2);
结果如下:
Create simpleSample2
number=1 and number2=2
可见通过set访问器可在访问字段时进行操作,同时通过设置读写权限完成封装操作。
2.接口和权限修饰符
封装就是对代码、程序进行保护。通过权限修饰符保护代码的可访问性,再提供接口,用户在不清楚实现细节的基础上就可以使用代码,完成了封装效果。
具体过程一般就是从类中抽象出函数原型再组成C#中Interface,就完成了提供接口。