2面向对象

mac2022-06-30  149

面向过程:分析出解决问题所需要的步骤,即简单的处理问题

面向对象  把构成问题的事物分解成各个对象,简化程序的开发,面向对象内部的实现,写的还是面向过程的代码,它们是一个互补的关系。

三大特点:

① 封装:把客观事物封装成抽象的类;

② 继承:子类可以使用父类的所有功能,并且对这些功能进行扩展,子类也可以定义自己的功能;

③ 多态:同种事物,多种形态,名称相同,行为方式(实现的内容)不同,这种现象就称为多态。例如,老师和学生都需要上课,但老师是授课,而学生是听课。

多态有两种方式:覆盖(子类重新定义父类的方法)和重载(一个类中允许存在多个同名方法,而这些方法的参数不同)

被继承的类叫基类或者叫父类,继承父类的类叫子类或者派生类,子类扩展了父类。

 

分为数据成员(字段)和函数成员(属性、构造函数)--行为

定义一个对象:类名 方法名

 

字段:访问修饰符+数据类型+名称(首字母小写)

只读字段:readonly,在程序运行过程中,有一次在构造函数里赋值的机会,对象.字段名,

静态字段①static,和对象无关,和类有关,所有的对象都共同具有的特点;

②—调用它时,用类名.字段名 ;

③在静态构造函数中初始化

 

常量:

① 当跟对象无关时,就会用到常量;

② 定义一个常量,所有字母都要大写,单词与单词之间用下划线连接

③ 常量--在编译之前就确定值,并且在程序运行过程中不会发生改变

④ 常量的调用方法是:类名.常量名

Const和readonly比较

相同点:都是用来标识常量的,const用来定义静态常量,readonly用来定义动态常量;

不同点①const在编译前初始化,其值一经确定不能修改,readonly有一次在构造函数里赋值的机会;

②const与对象无关,调用它用类名.常量名,而readonly与对象有关,调用它用类名.字段名。

属性对字段进行封装,get set

构造函数:访问修饰符+类名(参数列表)

public Student(string name, int age)

        {

// this代表当前这个对象(当前这个对象的name等于你传进来的这个name)       

this.name = name;

            this.age = age;

        }

① 是用来创建对象的,可以做一些初始化的设置(给类的字段、属性赋值);

② 如果没有定义构造函数,编译器也会给一个默认的构造函数(空的即无参数构造函数),当我们提供一个构造函数后,系统提供的就没有了;

③ 可以有多个构造函数(参数列表不一样),它们在一个类中;

④ 构造函数没有返回类型

静态构造函数:static 类名(){},它没有也不能加访问修饰符

用来初始化静态常量

static Student()

        {

            company = "863";

        }

Console.WriteLine("您的公司是{0}", Student.company);

string sc = Student.company;

            Console.WriteLine("您的公司是{0}",sc);

形式参数--形参,实际参数--实参

构造函数的重载:有多个构造函数,名称相同,通过参数列表区分

方法(函数):访问修饰符+返回类型+方法名+参数列表

方法是用来定义对象的行为;

调用方法:对象.方法名(参数);

当方法没有参数,没有返回值时,就用void

public void 方法名()

{           Console.WriteLine("再见");

            return;//这个方法调用完就跳出了

}

静态方法static,调用时用类名.方法名

静态类:它所有成员都必须是静态的,没有对象,没有构造函数,不能初始化

方法的重载:在同一个类中,方法的名称相同,方法的签名不同(参数列表不同)

方法的重写:在不同的类中,方法名称相同,参数列表相同,内容不同;

要加一个关键字:virtual 虚方法—允许子类重写

子类重写父类的虚方法:override

调用基类用关键字base;

调用自己用关键字this。

方法的隐藏:用new关键字;

值传递:方法调用的时候,传递的是参数的副本。(当参数是值类型的时候)

引用传递:方法调用的时候,传递的是参数本身。(当参数是引用类型的时候)string类型除外,它传递时相当于值传递

ref:将值传递变为引用传递

out:输出参数,

运算符重载:operator

public static Box operator +(Box b1,Box b2)

        {

            Box box = new Box();

            box.a = b1.a + b2.a;

            box.b = b1.b + b2.b;

            box.c = b1.c + b2.c;

            return box;

        }

索引器:对象后面加[],里面填索引号

ShoppingCar car = new ShoppingCar();

            Goods g = car[0];

 

http://www.cnblogs.com/joeylee/p/3631246.html

继承简化类的设计

现实世界遗传关系的直接模拟表示类之间的内在联系以及实现属性和操作共享

C#中一个类只能继承一个类(没有明确写的话默认继承object类)

继承中构造函数的执行顺序,由父类开始,沿着继承链向下执行

实例化子类对象的时候构造函数是顺着继承链先往上找,然后从父类开始,每个父类的构造函数都会被继承一遍

c#类的初始化顺序

子类的静态成员变量,子类的普通成员,父类的静态成员,父类的普通成员

首次访问:(在此没有显示的写出类中的构造方法)

顺序:子类的静态字段==》子类静态构造==》子类非静态字段==》父类的静态字段==》父类的静态构造==》父类的非静态字段 ==》父类的构造函数==》子类的构造函数 

非首次访问:顺序是一样的,只不过少了中间静态字段和构造的过程 

对于静态变量与静态构造函数而言, 无论对一个类创建多少个实例,它的静态成员都只有一个副本。 也就是说,静态变量与静态构造函数只初始化一次(在类第一次实例化时)

基类(父类):被继承的类;调用基类用关键字base;

扩充类(子类):去继承的类;调用自己用关键字this。

class Program

    {

        static void Main(string[] args)

        {

            Father f=new Son();

            Console.WriteLine(f.age);   //这里输出的是父类的年龄?还是子类的年龄? 答案是父亲的年龄 70 ,因为这里的f是个父类类型,所以是调用父类的属性

            Son s = f as Son;

            Console.WriteLine(s.age);  //这里输出的父类的年龄?还是子类的年龄? 答案是子类的年龄 30

            Console.ReadKey();

        }

        public  class  Father

        {

            public int age = 70;                      //第4执行

            public static string name = "父亲";       //第3执行

        }

        public class Son : Father

        {

            public int age = 30;                    //第2执行

            public static string name = "儿子";    //第1执行

         }

    }

 

方法的重载:在同一个类中,方法的名称相同,方法的签名不同(参数列表不同)

方法的重写:在不同的类中,方法名称相同,参数列表相同,内容不同;

要加一个关键字:virtual 虚方法—父类的方法允许子类做一些修改,ToString是一个虚方法

子类重写父类的虚方法:override

 

父类变量指向子类的实例,但是我们直接调用父类变量下的属性,会输出子类的属性?还是父类的属性?答案是父类的属性.

那如果再继续调用方法的话,是调用父类的方法?还是子类的方法?答案是,如果是虚方法,子类有重写,就调用子类的,子类没有重写,就调用父类的.

 

 

 

 

 

 

总结

1:当用父类的变量调用属性的时候,取决于声明的类型(“=”左边是什么类型),而不是后面实例化的类型。例如 输出 f.age 就是输出父类的属性 ,而不是子类的属性

2:当子类和父类的方法完全相同时,调用的时候取决于声明的类型(“=”左边),而不是后面实例化的类型。

也就是子类没有重写的时候. f.sayhi 就是调用的父类的sayhi ,而不是子类的sayhi

3 如果子类有重写(override)父类的方法,那么 父类变量调用方法的时候,就变成使用 子类的方法.

也就是子类有override的时候,f.sayhi 就是调用子类的sayhi

4:如果想在子类里面访问父类的属性或者是方法,使用 base 关键字

 

方法的隐藏:在不同的类中,方法名称相同,参数列表相同,内容不同;用new关键字;

C#newoverride的区别

①当父类里面有 virtual 方法的时候,子类可以使用 override 进行重写.  那么  f.sayhi  就变成调用子类的sayhi

②不论父类的方法有没有virtual,子类都可以在同名的方法上加一个new表示这是子类自己的方法,那么父类的方法就会被隐藏起来, f.sayhi 就会变成 调用父类的sayhi,因为子类并没有override. 如果这个时候,把new去掉,效果也是一样的,f.sayhi 也是调用父类的sayhi, 判断是否调用子类的方法,就看子类是否有override重写.

C#中,overridenew都会覆盖父类中的方法。那它们两者之前有什么区别呢? ①override是指“覆盖”,是指子类覆盖了父类的方法。子类的对象无法再访问父类中的

②new是指“隐藏”,是指子类隐藏了父类的方法,当然,通过一定的转换,可以在子类的对象中访问父类的方法。

 

partial类:当一个文件太大时,把它分成两个文件,每个文件都可以获取另一个文件的内容。比如我在1.cs文件定义了一个Student类,在2.cs文件里定义了一个public partial class Student类,那么写在partial类里面的字段1.cs同样可以获取

抽象类abstract:

①专门做基类(它肯定有子类),让别人来继承,不能实例化对象;

②抽象类里有抽象方法(不一定所有方法都是抽象的),抽象方法(没有方法体)必须在子类中实现

③虚方法子类不一定重写,但抽象类中子类一定要override重写

密封类:sealed,不允许被继承,不可能有子类

接口:Interface

定义接口public interface IName{}

①只有声明部分,没有实现部分,接口里面的方法是不需要访问修饰符的也不用实现

② 一个类只能继承一个类,但可以继承多个接口(接口和接口之间用逗号隔开)

③ 接口中包含事件,索引器,方法,属性, 但不能定义字段、构造函数、常量、委托;

④ 类和结构可以继承多个接口,接口自身也可以继承多个接口。

 

接口和抽象类的区别

相同点都不能实例化都包含未实现的方法其子类必须实现所有未实现的方法

不同点

① 抽象类作为有意义的实例的基类,在业务逻辑中起到基础的作用;而接口是作为模块与模块间,系统与系统之间的交互协议;

② 二者声明的关键字不同,接口的关键字为interface,抽象类的关键字为object;

③ 继承方式不同:子类可以实现多个接口的继承,而只能继承一个抽象类;

④ 方法声明的使用不同:接口中直接给出了方法头,方法在被使用时可以直接实现方法;抽象类中使用abstract声明方法头,方法被使用时需要使用override关键字实现方法。

委托delegate把方法作为参数传递给另一个方法

访问修饰符 delegate void 委托名(参数列表)参数列表可为空

Main方法、Winform控件也是一个委托

 

事件event用来封装委托

事件和委托区别

委托是一个类它定义了方法的类型可以把方法作为另一个方法的参数进行传递,声明委托的关键字为delegate,事件是一种特殊的委托,是类和对象对外发出的消息,声明某行为或某处理条件已成立,即类和对象在发生其关注的事情时用来提供通知的一种方式。

结构体:值类型,而类是引用类型

访问修饰符(5种):

Public(公有的)

Private(私有的,只有类内部可以访问,子类是可以继承的,但不可以访问)

Protected(受保护的,只有类自己和子类才可以访问)

Internal(应用程序集(一个一个的项目),  应用程序集内部可以访问)

修饰类的只能用public或者是internal

Protected Internal

 

String 和StringBuilder的区别:

二者的功能相似,他们最大的不同在于当生成一个新的string时,string会重新开辟一个新的内存空间,而StringBuilder则在原来的内存中进行修改;

所以,当面临需要多次修改的情况时,用StringBuilder比较合适。

Array ArrayList HashTable的区别

Array:存储类型统一,长度固定,在一开始声明的时候,长度就固定了,堆内存为之分配相对应的内存空间;静态,不灵活;

ArrayList:解决的Array的缺点,它的长度是动态变化的,随着add对象的增加,它的数量(count)逐一增加,它的容量(capacity)成倍(2是指数倍),同时它的存储对象是object类型,即对存储类型没有任何限制,但是它的查询效率比较低;

HashTable:解决了ArrayList的缺点,它的存储对象也是object类型,它可以自定义对象的索引,加速了数据的索引效率。

 

Ref和out区别:

相同点:ref和out都是按地址进行传递的,使用后都将改变原来参数的值;

不同点①ref把参数的数值传进函数是会将其原有的数值改变;而out则是直接清空参数的数值;②运行时的处理方式不同,传递到ref参数的参数必须最先初始化,而out参数在传递之前不需要显示初始化。

 

                                                 

转载于:https://www.cnblogs.com/wanghuixia/p/9533618.html

最新回复(0)