1,面向对象
什么是面向对象?一个分析问题的方式(增强了程序的可扩展性)
几个名词解释
OOP:面向对象编程
OOA:面向对象分析
OOAD:面向对象分析与设计
面向对象技术的优点:能够构建与现实世界对应的问题模型,并保持他们的结构,关系和行为模式。
面向对象的三大特征:封装,继承,多态
什么是类?什么是对象?类和对象的区别?
语法:
[public] class 类名
{
字段;
属性;
方法;
}
那么,我们管创建这个类的对象过程称之为类的实例化。
使用关键字 new.
this:表示当前这个类的对象。
类是不占内存的,而对象是占内存的。
结构式面向过程的 类是面向对象
1)类是模具,创建对象的模具,是抽象的
2)类是数据类型,用户自定义的数据类型
3)类的组成:字段,属性,方法,构造函数等
4)对象是具体的,是类的具体实例,对象具有属性(特征)和方法(行为)
5)类中包含了数据(用字段表示)和行为(用方法表示)
在类中用数据表示事物的状态,用函数实现是事物的行为。
类中的成员不写访问修饰符,默认是private
在dotnet中类(class)与结构(struct)的异同?
Class可以被实例化,属于引用类型,是分配在内存的堆上的。类是引用传递的。
Struct属于值类型,是分配在内存的栈上的。结构体是复制传递的。加分的回答:Int32、Boolean等都属于结构体。
属性
属性的作用就是保护字段、对字段的赋值和取值进行限定。属性的本质就是两个方法,一个叫get()一个叫set()。
既有get()也有set()我们诚之为可读可写属性。只有get()没有set()我们称之为只读属性。没有get()只有set()我们称之为只写属性
当你输出属性的值得时候 会执行get方法 当你给属性赋值的时候 首先会执行set方法
当属性的字段为只读时,可以再构造函数中给属性赋值。
属性和public字段的区别是什么?调用set方法为一个属性设值,然后用get方法读取出来的值一定是set进去的值吗?
属性可以对设值、取值的过程进行非法值控制,比如年龄禁止设值负数,而字段则不能进行这样的设置。虽然一般情况下get读取的值就是set设置的值,但是可以让get读取的值不是set设置的值的,极端的例子。Public
Age{get{return 100;}set{}}。加分的补充回答:用reflector反编译可以看出,属性内部本质上就是set_***、get_***方法
析构函数 ~Studeng() 析构函数当程序结束时才执行,帮助我们释放资源。如果GC在程序结束时来不及释放资源,可以使用析构函数。
2,类的构造函数
1)编写完类以后,这个类默认有一个无参的构造函数,
2)只要为这个类手动添加一个构造函数,会自动将原有的无参构造函数覆盖掉
3)构造函数的特点:函数名称与类名完全一致;构造函数没有返回值,哪怕void也不能写;构造函数也是可以重载的;一般情况下,构造函数的访问修饰符是public;编写类后,有一个默认的无参的构造函数
plaincopy
- public class Student
- {
- public Student()
- {
- }
- public Student(string name)
- {
- }
- public Student(string name, int age)
- {
- }
- public Student(string name, int age, int height)
- {
- //通过构造函数初始化类成员。
- this.Name = name;
- this.Age = age;
- this.Height = height;
- }
- ////.net中的终结器Finalize();
- //~Student()
- //{
- //}
- public string Name
- {
- get;
- set;
- }
- public int Age
- {
- get;
- set;
- }
- public int Height
- {
- get;
- set;
- }
- /// <summary>
- /// 学号
- /// </summary>
- public string SNo
- {
- get;
- set;
- }
- }
3,变量作用域
离声明该变量最近的那对包含声明语句的大括号内部
成员变量一直属于某个类,作用域在该类内部
成员变量如果使用前不赋值,默认会有一个初始值:string ------>null int------->0 bool-------->false
局部变量------声明该变量的块语句或方法结束的封闭括号之前的作用域内(使用之前必须赋值)
4,封装
面向对象的封装就是把事物的状态和行为封装在类中,使用类的人不需要知道类内部是怎么实现的,只要调用其中的属性和方法实现功能就行。
类和对象本身就是封装的体现, 1)属性封装了字段,2)方法的多个参数封装成了一个对象,3)将一堆代码封装到了一个方法中,4)将一些功能封装到了几个类中,5)将一些具有相同功能的代码封装到了一个程序集中(dll,exe)并对外提供统一的访问接口。
封装的特点:1)隐藏代码的实现,便于用户调用,2)让代码和实现相分离,3)在类的内部实现*的修改
封装复杂的,变化的东西,暴漏给用户简单的稳定的。
5,继承
继承:指类与类之间的关系。
如何判断一个继承关系是否合理?子类 is a 父类
为什么要继承?继承带给我们的好处?
1)代码重用
2)LSP(里氏替换原则)(通过代码说明一下,声明父类类型变量,指向于类类型对象,以及调用方法时的一些问题),多态(程序的扩展性,灵活性),方法重写override,虚方法的处理。
子类继承父类的属性和方法,使创建类变得简单,实现了代码重用,以及多态。
继承的特性:1)单根性,不允许多继承,一个类只能继承自一个父类,2)传递性,3)类的构造函数是不能被继承的,只能在子类中去调用父类的构造函数
所有的类都直接或间接的继承自object。
继承还有一个重要特性,父类对象可以引用子类实例,
将子类对象赋值给父类对象,所得到的对象时这样一个对象:他是一个编译是父类对象,运行却是一个子类对象,具体特征如下:1)被声明为父类对象,2)拥有父类属性,3)占用子类的内存空间,4)子类方法覆盖父类方法时,此时对象调用的是子类的方法,否则,自动调用继承父类的方法
继承中this和base的区别
1)this,(1)当做类的 对象,可以调用类中的成员,this.成员,(2)调用本类的其他构造函数 :this() (调用构造函数自己)
2)base,1.调用父类中的成员(在子类重写父类成员或者子类使用new关键字隐藏了父类成员时,调用父类成员)base点不出子类独有成员。2.调用父类中的构造函数(调用构造函数,父类)
plaincopy
- class Program
- {
- static void Main(string[] args)
- {
- //FileStream fs = new FileStream(@"c:\aa.txt", FileMode.Create);
- Teacher t1 = new Teacher("杨中科", 18, "yzk@itcast.cn", 1000000);
- Student s1 = new Student("陈超", 19, "cz@yahoo.com", "100001");
- }
- }
- //构造函数不能被继承。
- //由于在创建子类对象的时候,一定会调用子类的构造函数,而任何一个子类构造函数默认情况下都会去调用父类的无参数的构造函数,所以当父类中没有无参数的构造函数时就出错了。
- //解决办法:
- //1>在父类中增加一个无参数的构造函数
- //或者
- //2>在子类中指定子类的构造函数调用父类中的有参数的那个构造函数。
- class Person
- {
- public Person()
- {
- Console.WriteLine("========================");
- }
- public Person(string name, int age, string email)
- {
- this.Name = name;
- this.Age = age;
- this.Email = email;
- }
- public string Name { get; set; }
- public int Age { get; set; }
- public string Email { get; set; }
- }
- class Teacher : Person
- {
- public Teacher(string name, int age, string email, double salary)
- : base(name, age, email)
- {
- //this.Name = name;
- //this.Age = age;
- //this.Email = email;
- this.Salary = salary;
- }
- public double Salary { get; set; }
- }
- class Student : Person
- {
- //通过:base(),手动指定子类个构造函数去调用父类的哪个构造函数。
- //注意执行顺序是:先调用父类的构造函数,然后再执行子类自己的构造函数。
- public Student(string name, int age, string email, string sno)
- : base(name, age, email)
- {
- //this.Name = name;
- //this.Age = age;
- //this.Email = email;
- this.SNo = sno;
- }
- //学号
- public string SNo { get; set; }
- }
- //通过:this()调用本类中的其他构造函数
- //:base()调用父类的构造函数
- //:this()调用当前类中的其他构造函数。
- public class MyClass
- {
- public string Name { get; set; }
- public int Age { get; set; }
- public int Height { get; set; }
- public string Email { get; set; }
- public MyClass()
- {
- }
- public MyClass(string name, int age)
- : this(name, age, 0, null)
- {
- }
- public MyClass(string name, string email)
- : this(name, 0, 0, email)
- {
- }
- public MyClass(string name, int age, int height, string email)
- {
- this.Name = name;
- this.Age = age;
- this.Height = height;
- this.Email = email;
- }
- }
方法重写:
plaincopy
- internal override void T1(int n)
- {
- base.T1(n);
- }
new关键字 :1)、创建对象 2)、隐藏从父类那里继承过来的同名成员。隐藏的后果就是子类调用不到父类的成员。