1.1面向对象编程
含义:用程序来抽象对象,用面向对象的思想来编程。
原因:提高代码的复用性,提高效率,提高提高程序可拓展性,清晰的逻辑关系
面向对象的知识
类(class),
*****************************************************
面向对象三大特性:封装+继承+多态
封装:用程序语言来形容对象
继承:复用封装对象的代码,儿子继承父亲,复用现成代码
多态:同样行为的不同表现,儿子继承父亲但是有不同的行为表现
*****************************************************
面向对象七大原则:开闭原则,依赖倒转原则,里氏替换原则,单一职责原则,接口隔离原则,合成复用原则,迪米特法则
1.2类和对象
(1)什么是类?
具有相同特征,相同行为的一类事物的抽象
类是对象的模板,可以通过类创建出对象
(2)类声明在哪里?
一般声明在namespace中
(3)声明语法
class 类名//前可加访问修饰符
{
//特征——成员变量
//行为——成员方法
//保护特征——成员属性
//构造函数和析构函数
//索引器
//运算符重载
//静态成员
}
(4)实例
命名用帕斯卡命名法
注意:同一语句块中的不同类不能重名
class Person
{
//特征——成员变量
//行为——成员方法
//保护特征——成员属性
//构造函数和析构函数
//索引器
//运算符重载
//静态成员
}
(5)什么是(类)对象?
就是类声明出来的变量
基本概念:
类的声明和类对象(变量)声明是两个概念
类的声明类似枚举和结构体的声明,类的声明相当于声明了一个自定义的变量类型
对象是类创建出来,相当于声明了一个制定类的变量,类创建对象的过程一般称为实例化对象
类对象都是引用类型;
(6)实例化初始对象
类名 变量名
类名 变量名=nulll;
Person p;//栈上分配空间,没放地址,没有在堆上分配空间
Person p2=null;//没有在堆上分配空间
Person p3=new Person();//堆上分配了地址,相当于一个人对象
Person p4=new Person();//相当于又是一个人
注意:虽然他们来自一个类的实例化对象,但是他们的特征 行为信息都是他们独有的,不会是共享了数据,两个人是不同的
1.3成员变量和访问修饰符
(1)成员变量
声明在类语句块中,用来描述对象的特征,可以是任意变量类型,数量不做任何限制,是否赋值根据需求来定
enum E_SexType//枚举,结构体,类都是
{
Man,
Woman,
}
struct Position
{
}
class Pet
{
}
class Person
{
//特征
string name="我";//与结构体不同,类中这里可以初始化
int age;
E_SexType sex;
Person girlFriend;//这里和结构体不同,在类里面是可以申明一个与类名相同的变量的,
//结构体之所以不能声明与结构体名相同的变量,是因为结构体是值类型,他创造一个过后,如果里面的成员还有同类型结构体则会不断地创造,栈会不断地分配空间,很快就会爆栈,而类是引用类型,如果只是声明就不会分配内存地址,所以不会爆栈。
//所以要注意,类中相同名称的类不能初始化(不能写Person girlFriend=new Person();可以写成Person girlFriend=null;),否则就和结构体中有相同名称的结构体一样,会爆栈。
Person[]boyFriend;
Position pos;
Pet pet;
}
********************************************************************
访问修饰符
内部是指类的内部
public——公共的 自己(内部)和别人(外部)都能访问和使用
private——私有的 自己(内部)才能访问和使用 不写默认为private
protected——保护的 自己(内部)和子类才能访问和使用
********************************************************************
成员变量的使用和初始值
//值类型来说 数字类型 默认值都是0 bool类型false
//引用类型的初始值都是null
如何知道一个类型的默认值?
Console.WriteLine(default(各种类型:比如说int,char等));
*******************************************************************
1.4成员变量的声明
成员函数来表现对象行为
声明在类语句块中,是用于描述对象的行为的,规则和函数申明的规则相同,受到访问修饰符规则影响,返回值参数不做限制,方法数量不做限制
注意:成员方法不要加static关键字,必须实例化对象后,再通过对象来使用,相当于该对象执行了某个行为,成员方法受到访问修饰符影响
******************************************************************
举例:
Class Person
{
public string name;
public int age;
public void Speak(string str)
{
Console.WriteLine("{0}说{1}",name,str);
}
public bool IsAdult()
{
return age>=18;//这里返回值是个布尔
}
}
*****************************************************************
类函数的妙用
比如现在有一个关于人的类,类中有一个存储朋友的数组,要实现增加朋友的功能,可以新加一个加朋友的方法。
Class Person
{
public string name;
public int age;
public Person[] friends;
public void Speak(string str)
{
Console.WriteLine("{0}说{1}",name,str);
}
public bool IsAdult()
{
return age>=18;//这里返回值是个布尔
}
public void AddFriend(Person p)
{
//首先应该判断有没有朋友,这里不应该判断数组的长度,因为是引用类型,所以应该直接判断是否为空
if(friends==null)
{
friends=new Person[]{p};
}
else
{
//如果已存在朋友就要进行数组搬家
Person[] newFriends=new Person[friends.Length+1];
for(int i=0;i<friends.Length;i++)
{
newFriends[i]=friends[i];
}
newFriends[newFriends.Length-1]=p;
friends=newFriends;//这样就还是用friends这个名字
}
}
}
1.5 构造函数与析构函数
(1)构造函数
基本概念:在实例化对象的时候 会调用的用于初始化的函数,若没有自己写的构造函数会调用默认的构造函数。
用法:
没有返回值,函数名和类名必须相同,没有特殊要求一般都是public的,构造函数可以被重载,this代表当前调用该函数的对象自己
注意:
如果自己没有实现无参构造函数而实现了有参构造函数就会失去默认的无参构造
类中允许自己声明无参构造函数,结构体不允许自己声明无参构造函数
一般为了不每次都单独为一个变量赋值,可以专门写一个构造函数,对类中的各种属性进行初始化赋值。
public Person (int age,string name)//这里使用的是重载
{
this.age=age;
this.name=name;
}
//使用时就传值
Person p=new Person(18,"Nicela");
(2)构造函数特殊写法
(3)析构函数
(4)垃圾回收机制
1.6成员属性
(1)作用:
1.用于保护成员变量
2.为成员属性的获取和赋值天增加逻辑处理
3.解决3P的局限性
public——内外访问
private——外部访问
protected——内部和子类访问
属性可以让成员变量在外部
只能获取 不能修改 或只能修改不能获取
(2)成员属性的基本语法
访问修饰符 属性类型 属性名
{
get{}
set{}
}
*****************************************************
举例:
get,set好像既可以改也可以获取,为什么不直接对name进行public处理呢?
因为这里除了改变值之外还可以进行一系列逻辑,比如保护逻辑和加密逻辑
保护逻辑:
加密逻辑
(3)访问权限
*******************************************************************
举例:
public int Money
{
get//这里没有写修饰符,则采用属性声明的修饰符public
{
return money-5;
}
set//这里没有写修饰符,则采用属性声明的修饰符public
{
money=value+5;
}
}
************************************************************************
举例:
public int Money
{
private get//这里写private修饰符则表示不可得,只改不得,比如不可用Person类生成的对象.get获得返回值
{
return money-5;
}
set//这里没有写修饰符,则采用属性声明的修饰符public
{
money=value+5;
}
}
**************************************************************************
public int Money
{
get//这里没有写修饰符,则采用属性声明的修饰符public
{
return money-5;
}
private set//这里没有写private修饰符,则只读不改
{
money=value+5;
}
}
***************************************************************
不能为属性的两个访问器同时指定可访问性修饰符
public int Money
{
private get//报错
{
return money-5;
}
private set//报错
{
money=value+5;
}
}
***************************************************************
加的访问修饰符必须要比低于属性的访问修饰符,不能一样也不能比它权限大
private int Money
{
private get//报错,首先权限和属性权限一样,毫无作用,其次,get和set都有权限,报错
{
return money-5;
}
private set
{
money=value+5;
}
}
****************************************************************
private int Money
{
public get//报错,get权限大于外面属性的权限
{
return money-5;
}
set
{
money=value+5;
}
}
(4)get和set可以只有一个
一般会出现只有get的情况,基本不会出现只有set的情况
public bool Sex
{
get
{
return sex;
}
}
(5)自动属性
作用:外部能得不能改的特征
如果类类中有一个特征是只希望外部能得不能改的,又没有什么特殊处理(没有逻辑处理)
那么就可以直接使用自动属性
public float Height//这样写不用再在类中写float height;相当于自动会有一个变量来存储height
{
get;//
private set;
}
1.7索引器
基本概念:让对象可以像数组一样通过索引访问其中元素,使程序看起来更直观,更容易编写
语法:
访问修饰符 返回值 this[参数类型 参数名 ,参数类型 参数名...... ]
{
内部写法与索引器相同
get{}
set{}
}
//外面像函数,里面像索引器
********************************************************
//索引器往往是在类外部去访问类里部的某个数组,为了方便访问就会用索引器
class Person
{
private string name;
private int age;
private Person[] friends;
public Person this[int index]
{
get
{
if(friends==null||friends.Length-1<index)
{
return null;
}
return friends[index];
}
set
{
if(friends==null)
{
friends=new Person[]{value};
}else if(index>friends.Length-1)
{
friends[friends.Length-1]=value;//也可以是其他的逻辑
}
friends[index]=value;
}
}
}
//索引器的使用
Person p=new Person();
p[0]=new Person();//有了索引器就可以直接用数组形式访问
Console.WriteLine(p[0]);
//但是这样写是会报错的,因为类中的friends数组是空的,只是声明了,这样写直接去调一个空数组的第一个元素是会报错的,此时可以利用索引器对其进行预防。
********************************************************************
//索引器的重载
//这样写会报错,因为二维数组没有初始化,指向null,无法返回值
//索引器中参数可以写任意类型
1.8静态成员
//静态函数不需要实例化,可以直接通过类名.静态方法进行调用
//静态函数不能使用非静态成员,因为非静态成员必须要被实例化后才会被分配空间,才能被使用,不能无中生有,不能去访问一个没有的东西
//非静态函数可以使用静态成员
原因与上相同,因为非静态函数必须实例化后才会使用,静态函数在程序一开始就会分配内存进行使用,这都不会无中生有
//注意不要随意做成静态,因为静态变量和静态函数在程序运行时是一直占据内存的,一直不释放,这样就会导致动态空间太小,会频繁的=地进行GC,频繁地GC就会造成程序的卡顿。
******************************************************************
*********************************************************************
1.9静态类与静态构造方法
******************************************
//静态类中不允许使用非静态成员
//静态类中的静态构造函数
//普通类中的静态构造函数
注意:静态和非静态构造函数不能算重载
//通过调用结果可以看出静态构造函数都是在程序运行最开始进行调用
*****************************************************************
2.0拓展方法
*************************************************************************
***************************************************************************
*****************************************************************************
******************************************************************************
注意:如果拓展方法的方法名和原类中的方法名称相同,比如下面Fun3改为Fun2则在调用时会调用自己的Fun2即输出456;
*************************************************************************
**********************************************************************************
2.1封装,运算符重载
概念:让自定义类和结构体能够使用运算符
关键字:operator
特点:
1.一定是一个公共的静态方法
2.返回值写在operator前
3.逻辑处理自定义
作用:
让自定义类和结构体对象可以进行运算
注意:
1.条件运算符需要成对实现
2.一个符号可以多个重载
3.不能使用ref和out
4.参数列表的顺序是有关系的,比如+号是二元运算符,第一个参数是+号前面那个数,第二个参数是+号后面那个数,不同的参数类型调换位置也算是一种重载
5.参数列表的个数与运算符的运用规则有关,比如加号只能两个两个加,所以参数列表的个数只能是两个。
********************************************************
**********************************************************
注意:参数列表中的参数类型必须至少有一个包含类型
比如:上图中的Point类中重载了+号,其中参数列表中至少要有一个是Point类型的,不能出现比如两个int参数的情况。
从使用上也可以看出,重载的函数必须是静态的,因为重载运算符是直接运算的,肯定不会进行初始化对象
***********************************************************************************
同一运算符可以进行多次重载,这里就出现了一个point一个int的参数列表
******************************************************************************
可重载的运算符:
算数运算符
//条件运算符是相对称的,要一起写
不可重载的运算符:
**********************************************************
*****************************************************************
2.2内部类与分部类
(一)内部类
概念:在一个类中再声明一个类
特点:使用时要用包裹者点出自己
作用:亲密关系的变现
注意:访问修饰符作用很大
实际上是一个类
*****************************************************************************************
2.3继承的基本规则
(1)基本概念
(2)基本语法
使用: