自己用的C#基础学习笔记(二)——C#面向对象(1)

C#面向对象

第八天

1.1 对象和类

相同属性和方法的对象 的特性进行封装,抽象出类的概念。

类创建出来,如果不做调用,不占用内存,只有创建对象的时候才会开辟空间。

1.1.1 类的语法

[public ]  class 类名{

字段;

属性;

方法;

}

1.1.2 字段

字段一般下划线开头

让其他类使用该字段必须将字段共有,即加上public

不写默认不是public

私有的字段只能本类内使用

1.1.3 属性

对字段的保护,避免非法值的输入。属性都有get{}set{}方法(注意没有小括号),可以通过这两个方法来控制字段的输入和输出内容

属性名可以和公共的枚举名同名。

属性名应该根据保护的字段来取,让人一看能知道该属性属于哪个字段的。

public string Name{

get{//该方法在输出的时候会自动调用该方法。

return name(字段名);

}

set{//在赋值的时候会调用set方法

name(字段名)= value;//value为赋的值,处理时一定注意不要判断字段,而是判断valuevalue的数据类型是属性定义的数据类型。

}

}

有了属性之后,可以将字段私有,通过公有的属性来进行赋值获取,此时属性可以完全当做字段来使用,举例:

Person p = new Person();      p.Name=”1231”;

1.2 构造函数和析构函数

1.2.1 构造函数

函数名和类名相同,没有返回值,也不能写void,创建对象时自动调用。

一般用来给类的字段或通过属性赋初值。

举例:

Public Person(string name,int age,string language){//有参数构造函数

this.Name = name;

this.Age = age;

this.language = “adfsad”;/ this.language =language;

}

此时,调用有参数的构造函数时,创建对象时应加上参数,如下:

Person p1 = new Person(“dfasd”,23,”sfda”);

this是代表当前对象

不写构造函数时,会自动调用一个系统给的无参数的构造函数,自己写了会把系统给的覆盖掉,也就意味着,自己如果写了有参数的构造函数,实例化对象时,必须同时给予参数初始化字段,否则就得再写一个无参的构造函数。

1.2.2 析构函数

对象销毁的时候,自动调用,释放内存。

多个对象时,每销毁一个调用一次

~Person(){//波浪号是析构函数的标志

Console.WriteLine(“析构函数”);//程序结束时会自动销毁对象,此时会输出这句话

}

1.3 静态与非静态

1.3.1 静态函数与非静态函数

[public] static void 函数名

C#的主入口函数是静态的,所以只能调用静态方法

静态的函数只能调用静态函数,静态的函数只能使用(非自己的,例如全局变量,自己函数作用域内非静态也可以)静态的字段、属性或方法。

非静态的类中,可以有静态成员和非静态成员,非静态类调用类中静态方法,依然用类名.方法名

非静态类调用方法字段和属性时只能用对象来调用。

静态函数和字段的调用方式是用类名.方法名或字段名,而且只能使用类名

实例函数中即可使用静态,也可使用非静态

1.3.2 静态类

[public] static class 类名

静态类只允许有静态成员,但可以有常量(常量不分静态非静态),静态类不能实例化。

静态类的作用:

静态类一般用来作为工具类,可以进行数据共享(相当于全局作用域),静态类占用内存,所以在项目中静态类越少越好。

1.4 结构体和类的区别

1.4.1 结构体:

Public struct Student{

字段

属性

函数

构造函数,有默认无参,但是不能人为的手写无参构造,有参构造也不会覆盖默认无参(没有参数也没代码,必须有参数),全字段赋值(函数内所有字段都必须赋值,只赋值部分不行)

没有析构函数

}

结构体可以继承接口,不能继承类和结构体。

结构体的调用:Student s; s.属性/方法; 字段属性或方法只要是public,不实例化也可以调用,默认不写的不是public

结构体可以实例化。

Student s = new Student();

调用构造必须实例化。

1.4.2 类:

Public class Student{

字段

属性

函数

构造和析构函数

}

类内可以写结构体,但一般不会这么写

类是引用类型,存在堆中,传递地址。

结构体值类型,存在栈中。

1.5 命名空间

Namespace

命名空间相当于类的文件夹,可以避免类的重名。

不在同一命名空间的类可以重名,因为不在同一空间内。

如果类名和系统的类同名,不会报错(因为命名空间不同),但是此时只能调用自己的类,无法再调用系统命名空间的类了。

如果想用其它命名空间的类,需要引用对应的命名空间。

Vs中,在项目中右键引用,选择解决方案,选择对应的命名空间引用。同时在代码中写入using 命名空间名;举例:using System;

快捷键引入命名空间,alt+shift+F10

1.6 继承

解决冗余代码,把重复的成员封装成一个类,作为父类

语法:

类名:父类{

}

举例: public class Student:Person(基类,被继承类){

}官方称呼:继承类,被继承类

C#是单继承(单根性),一个类只能继承一个类,但是可以被多个类继承,可以有多道继承(传递性),但最好不要超过三个继承。

子类继承父类后,只能使用父类的公有字段或方法,不能继承私有的。

子类实例化会默认调用父类的无参构造,但是不会继承父类的有参数构造。

子类调用父类的构造函数,使用关键字 :base();

Base将参数的数值传给了父类的构造函数

举例:

Public student(sting name,int age,string hobby):base(name,age){//子类构造函数

This.Hobby = hobby;//nameage就不需要再写了,那两个通过base传递给了父类的构造函数

}

Public student(sting name,int age) {//父类构造函数

This.Name = name;

This.Age = age;

}

所有的类都继承与object

Vs命名空间右键,查看类图

1.7 Protected访问修饰符和new关键字

1.7.1 Protected

protected关键字,只能父类和子类中使用

1.7.2 new

new关键字实例化对象时,会覆盖父类的同名成员;

如果是故意隐藏,就在类名前加上new关键字,不写不会报错,但是编译器会提醒

1.8 里式转换

1、子类可以赋值给父类

举例

Person s = new Student();student为子类,person为父类。

如果有函数需要一个父类类型的值,我们可以给他一个子类,举例

String.Format(“fgsfd”,5);格式化字符串函数需要一个object类型的参数,给他int类型也不会报错。因为所有类型都是object类的子类。

2、如果父类里存的是子类对象,我们可以将这个对象强制转换为子类的对象。举例:

Person p = new Student();//此时父类person中存的是student的对象

通过isas关键词

Is表示类型转换,如果能转返回true,否则false,用于判定

If(p is student){//判断是否能转

Student ss = (Student)p;强制转换

}

As如果能转就直接返回转换过的对象,否则返回null。(又称安全型转换)

As的用法

Student ss = p as Student;

注意:父类得对象可以直接转换为子类对象,其实对应里式转换第一条,父类的变量和函数参数,可以赋值子类的对象。

Person[] p = new Person[10];

P[0] = new Student();此时p[0]student的对象。

因此可以for循环写

For(int i=0;i<p.Length;i++){

P[i] = new Student();

P[i].sayhello();//此时是student的对象

}

1.9 This的用法

This除了代表当前对象外,还有另一种用法:用this指向自己本类的构造函数

比如,当构造函数有多个时,其中有个参数最全,我们就可以通过this直接使用参数最全的构造函数初始化。写法如下:

Public Person(int age):this(age,”0”){

}

Public Person(int age,string name) {

This.name = name;

This.age = age;

}

第十天

2.1 多态(虚方法、抽象类、接口)

2.1.1 虚方法(只用于父类子类的继承关系)

virtual 父类中标记方法为虚方法。

子类中使用 override重写,此时虚方法可以重写,也可以不重写。

重写后,调用时就会调用本身的方法。

例如:

Person中有方法sayHi(){cw(“我是父类”)}student为继承,student中有方法sayHi(){

Cw(“我是子类”)

};

Public virtual void sayHi(){cw(“我是父类”);}

Public override void sayHi(){Cw(“我是子类”);}

Student s1 = new student();Student s2 = new student();Person p1 = new person();

Person[] p = new person[2]{s1,s2,p1};

P[0]/p[1].sayHi();//此时输出的是我的子类,不需要再进行is或者as判断转换了。

P[2].sayHi();输出依旧是我是父类

子类的子类(孙子类)没有重写虚方法时,直接调用会调用爷爷类?的方法。

2.1.2 抽象类和抽象方法

abstract抽象类和方法都是用该字段标志,共同特性比较多,差异较小的时候可以使用抽象类。

例如:public abstract class AA{ }

抽象类无法被实例化。抽象类也可以有实例成员,即正常的方法和属性字段,并且该类方法和属性字段也可以被继承

抽象类除了做父类,也可以做子类继承抽象类,也能继承普通类

抽象方法

父类的方法不知道如何是实现时,可以将方法写成抽象方法,但没有方法体。

public abstract void Voice();没有大括号

抽象方法可以在抽象类和接口,抽象方法必须要重写,签名(返回值和参数)要一致。

不能有抽象的字段,可以有抽象的属性、方法、事件。

2.1.3 接口

接口就是一种规范(或者说一种能力)

关键字:interface

接口中可以有属性,方法,索引器,事件。

接口成员不能有访问修饰符,默认public;接口的方法不能有具体实现;

举例:(一般接口名大写I开头)

Public interface IFly(){

Void fly();

Void run();

}

接口的方法不能有具体实现,需要到具体类中实现,继承了接口的类中必须将接口中的所有方法都实现了。

public class Bird:IFly{

public void fly(){

}

public void run(){

}

}

接口不能实例化

一个类可以继承多个接口,例如:

public class Bird:IFly,IChiBang{}

一个类可以继承另一个类的同时也可以继承接口,但是类必须写在前面,接口写在后面,用逗号分隔。例如:

Public class Bird:Animal, IFly,IChiBang{  }

接口可以继承接口,但不能继承类,继承接口的接口继承的方法不能实现,一般不会这么用。

如果继承接口的类中有和接口同名的方法,可以直接使用该同名方法作为接口的实现,也可以再单独实现接口:举例

public class Bird:IFly {

public void fly(){//类中原有的方法

}

Void Ifly.fly(){//实现接口的方法(显示实现接口),不通过这种方式,原同名方法会被默认为接口的实现方法。

}

}

上述情况接口的fly方法调用:Ifly f= new Bird();f.fly();

原有方法的调用:Bird b = new Bird();b.fly();

2.1.4 抽象类、接口和虚方法的使用区别

如果父类中的方法有实现,并且父类需要被实例化时,适用普通类,采用虚方法来实现多态。

如果父类中方法没有默认的实现方式,父类也不要被实例化,共同特性比较多的时候,可以将该类定义为抽象类。

共同特性比较少的时候,个体差异极大,可以使用接口。

2.2 装箱和拆箱

本质就是类型的转换。

将值类型转化成引用类型叫装箱

将引用类型转换值类型叫做拆箱

发生拆装箱的前提是转换类型的两者具有继承关系,object是所有类型的父类

例如:int a = 3;

Object b = a; //装箱(可以执行,结果正确,因为object是所有类型的父类)

Int c = (int)b;//拆箱;

2.3 值传递和引用传递

值类型传递传递值和地址

引用类型传递是传递的地址,所以引用类型通过赋值传递后,修改一个,另一个也会改变,例如数组。

类是引用类型,类中的值类型是存在堆中的。方法里的值类型是存在栈里。

引用类型在栈中和堆中都存有地址,且两个地址不同。

字符串是引用类型,但字符串有不可变性。

例如:string str1 = “cctv”;string str2 = str1; str1 = “cc”;

此时,str1 = “cc”; str2 = “cctv”;

因为字符串的不可变性,导致字符串定义后会开辟两个空间,虽然是引用传递,但修改其中一个的值不会改变另一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值