面向对象是一个抽象的概念,其本质就是对事物以抽象的方式建立对应的模型。
简单来讲,比如我有一只钢笔,那么我就可以通过分析,可以得到 这只钢笔的材第是塑料,品牌是个杂牌 ,里面装的墨是黑色的,可以用。这时候就能建立一个钢笔的模型,它在这里应该有这些属性:
图是一个不正确的uml类图,但是可以简单的概述一下我们抽象的结果。这个图就描述了一个我们抽象出来的钢笔类应该有哪些特性,而我手里的那只钢笔就可以看做是钢笔类的一个实例。
简单来讲,面向对象编程就是针对一个事件或者说一个过程,找到这个过程中参与的所有人、事务或者相对独立的个体,按照他们在这个过程中表现,提取出他们的特性,描述他们的行为,然后按照类别不同再抽象出类来。
所以,类是事物的概念抽象,事物是类的特殊实例。
上面简单的介绍了面向对象的概念,现在先创建一个c#类,然后介绍一下这个类需要注意的地方:
public class person { private static int count; public static int count { get { return count; } set { count = value; } } private string name; public string name { get { return name; } set { name = value; } } public person() { name = ""; count = count + 1; } public person(string name) { this.name = name; } public void sayhello() { } }
其中:
private string name;
和private static int count;
这两个在c#中称为field,也就是字段的意思;
public static int count
和public string name
这两个在c#中称为property,也就是属性的意思。
当然,不是说一个是private
就叫字段,另一个是public
就称之为属性,而是因为属性有get
和set
来控制访问和赋值的行为。
public person()
和public person(string name)
是构造方法,所谓的构造方法就是初始化一个实例的方法,调用形式如下:
person p = new person()
通过new关键字+类名+对应的参数列表即可。构造方法没有返回类型,方法名必须是类名,可以有任意个参数。
面向对象的三大特性是封装、继承、多态。我把它们称为面向对象面试三巨头,因为一旦面试,如果有面向对象的问题绝对会问到这三个特性。这里先简单介绍一下三大特性,
在将三大特性之前,先介绍一下 c#的访问控制。c#常用的访问控制分为四种:
c#还有更多的访问控制,不过常用的只有这四种,更多的可以参照【】。
封装简单来讲就是调用方不知道被调用方的具体实现以及内部机制,就像我们看别人只能看到外表缺看不到器官的运作(当然除非你是医生)。
那么封装有什么好处呢:
比如说一个钟表,给我们一堆零件,在没有拼接、安装好之前也就是封装好,这个钟表是不能正常使用的。只有我们按照一定逻辑,将零件安装好之后(封装),再装上电池或上发条(调用) 钟表才会转起来。
简单的用代码介绍一下:
class program { static void main(string[] args) { person p = new person(); p.sayhello(); } } public class person { private static int count; public static int count { get { return count; } set { count = value; } } private string name; public string name { get { return name; } set { name = value; } } public person() { name = "小明"; count = count + 1; } public person(string name) { } public void sayhello() { console.writeline("你好,我叫"+name); } }
简单看一下,对于program类来讲,person的sayhello是怎么实现的完全不知情。这就是封装的意义。
c#的继承是单继承,也就是说一个类只有一个父类,如果不指明父类,那么它的父类就是object
。换句话说,object
是c#继承体系里的根,也就是所有类的祖先类。
c#的继承用: 表示,即 class b: a
表示b继承a。
public class a { public virtual void say() { } public void look() { } } public class b : a { public override void say() { } }
上述代码建立了一个简单的继承体系。那么问题来了,继承有什么用呢?简单来讲,对于a和b在say方法有不同的实现,对于调用方来讲,它们的表现应当是一致的。换句话说,就是所有用到a的地方,都能用b来代替,这不会出现任何问题。
继承可以简化很多行为(方法)一致的写法。如示例所述,b类在look上与其父类a类有着一致的行为和表现,那么b就可以省略了look的定义和描述,沿用父类的方法。通过继承可以很快地建立一套丰富的方法体系。子类每一次对父类的方法补充都会在子类里体现出来。所以继承可以说是面向对象的核心体系。
有个关键字需要额外的讲解一下saled
,如果看到一个类有这个标记,那么需要注意了,这个类是不可被继承的类。
多态的实现就是通过类的继承和方法的重载实现的。类的继承主要通过重写父类方法或者覆盖父类方法来实现的,主要关键字就是 virtual
、override
、new
。
具体的介绍是:
public class a { public virtual void say() { //省略实现 } public void setname() { //省略实现 } } public sealed class b:a { public override void say() //重写父类方法 { //省略实现 } public new void setname() // 覆盖父类方法 { //省略实现 } }
重写和覆盖的区别在哪呢:
a a = new b(); a.say();// 调用的是 b中 say方法 a.setname();//调用的是a的setname 方法 b b = (b)a; b.setname();//调用的是b的setname 方法 b.say();// 调用的是 b中 say方法
c#中类和接口的声明方式不同,类用的关键字是class
,接口用的是interface
。而且类是继承,接口是实现,一个类只能有一个父类,接口可以有多个。
接口需要注意的地方就死,接口所有的方法都是public的,因为接口就是用来定义规范的,所以一旦它的方法访问控制不是public的话,就没什么意义。
public class demo1 { } public interface idemo { string method(); } public class demo3 : demo1, idemo { public string method() { return "test"; } string idemo.method() { return "test2"; } }
接口的实现和类的继承都是 : ,先继承后实现。
观察示例代码,发现demo3有两个方法public string method()
和string idemo.method()
。这两个都是实现接口的方法,不同的地方是它们的使用:
idemo idemo = new demo3(); idemo.method();//返回 test2 demo3 demo = new demo3(); demo.method();// 返回 test
使用接口名
.方法名
实现方法的时候,这个方法对于实现类构造的对象来说是不可访问的。当然两种方法可以共存,但是不会两个方法都被认为是接口的实现方法。接口优先使用接口名
.方法名
作为实现方法,如果没找到则认为同名同参的方法为实现方法。
object 作为基类定义了四个基本方法,这四个方法是所有子类都有的方法,也是一个核心方法:
==
运算符的结果,如果不重写这个方法的话,返回的结果是两个对象是否指向同一个引用地址。c# 有一个很重要的机制就是扩展方法,扩展方法表现出的跟类自有的方法调用结果一致。
具体写法如下:
public static class methods { public static string test(this person person) { return "test"; } }
需要注意的是,扩展方法所在类必须是静态类,扩展方法必须是静态方法,扩展方法第一个参数就是扩展的元素对象,用this标记。
不过很多人对扩展方法褒贬不一,有人认为扩展方法极易破坏继承链,导致一些不必要的麻烦;有人认为扩展方法就跟工具方法一样,而且可以优化调用方式,统一使用风格。
不过我看来,扩展方法利大于弊。因为扩展方法可以在不修改原有类的基础上增加功能,同时它也是一个工具类,跟普通的方法是一致的。
更多内容烦请关注
如对本文有疑问, 点击进行留言回复!!
C# 对PDF文档加密、解密(基于Spire.Cloud.SDK for .NET)
Unity通用泛型单例设计模式(普通型和继承自MonoBehaviour)
网友评论