20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)

1:C#中的访问修饰符

public: 公共成员,完全公开,没有访问限制。 

private: 私有的,只能在当前类的内部访问。

protected: 受保护的,只能在当前类的内部以及该类的子类中访问。

internal: 只能在当前项目中访问,在同一个项目中,internal和public的权限是一样的。

protected internal: protected + internal权限。

1.1:能够修饰类的访问修饰符只有两个: public / internal

1.2:接口中的成员不允许添加访问修饰符,默认是public

1.3:类中的成员不添加访问修饰符,默认是private

1.4:命名空间的成员不添加访问修饰符,默认是internal

2:继承(把这几个类当中重复的成员单独的拿出来封装成一个类,作为这几个类的父类)

我们可能会有一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类。

Student Teacher Driver 子类 / 派生类

Person         父类 / 基类

2.1:子类继承了父类,子类从父类继承过来什么?

子类继承了父类的属性和方法,但是子类并没有继承父类的私有字段。

2.2: Q:子类有没有继承父类的构造函数?

答:子类并没有继承父类的构造函数,但是,子类会默认调用父类无参数的构造函数,创建父类对象,让子类可以使用父类的成员。

解决方案:

1):在父类中重写一个无参数的构造函数。

2):在子类中显示的调用父类的构造函数,使用关键字:base()

2.3:继承的特性

 1.继承的单根性: 一个子类只能有一个父类

 2.继承的传递性:

2.4:查看类图

2.5:object是所有类的基类

2.6:new关键字

1):创建对象

2):隐藏从父类那里继承过来的同名成员(子类和父类具有相同名称的方法)

    隐藏的结果就是:子类调用不到父类的同名成员。

2.7:里氏转换

1:子类可以赋值给父类(如果有一个方法需要一个父类作为参数,我们可以传递一个子类对象)。

2:如果父类中装的是子类对象,则可以将这个父类强制转换为子类对象。

2.7.1:子类对象可以调用父类中的成员,但是父类对象永远都只能调用自己的成员。

2.8:is 和 as

is:表示类型转换,如果能够转换成功,则返回一个true,否则返回一个false。

as:表示类型转换,如果能够转换则返回对象的本身,否则返回一个null。

Ps: Q:代码中出现Error:可访问性不一致的原因

答:子类的访问权限不能高于父类,会暴露父类的成员

3:多态

3.1:实现多态的方法:

1):虚方法

    将父类的方法标记为虚方法,使用关键字virtual,这个函数可以被子类重新写一遍(override)

2):抽象类

    当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法

3):接口

3.2:抽象类

1.抽象成员必须标记为abstract,并且不能有任何实现。

2.抽象成员必须在抽象类中。

3.抽象类不能被实例化。

4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。

  (除非子类也是一个抽象类,则可以不重写)

5.抽象成员的访问修饰符不能是private

6.在抽象类中可以包含实例成员。

   并且抽象类的实例成员可以不被子类实现

7.抽象类是有构造函数的。虽然不能被实例化。

8.如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。

   如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候,也必须要有传入返回值。

3.3:虚方法/抽象类/接口 何时用来实现多态

1:如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

2:如果父类的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

3:几个对象没有共同的父类,但是有共同的行为。则可以使用接口实现

方法的签名:方法的返回值和参数

3.4:虚方法和抽象方法的比较

 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)

3.5:静态方法和实例方法(定义和调用)

20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)

3.6:设计模式

设计这个项目的一种方式 (简单工厂设计模式)

3.7:值类型在复制的时候,传递的是这个值得本身

      引用类型在复制的时候,传递的是对这个对象的引用

3.8:序列化与反序列化

序列化:就是将对象转换为二进制

反序列化:就是将二进制转换为对象

作用:传输数据

[Serializable] 只有被Serializable标记的类才能被序列化

 BinaryFormatter //序列化的类

 1     class Person
 2     {
 3         private string _name;
 4         private int _age;
 5 
 6         public string Name
 7         {
 8             get
 9             {
10                 return _name;
11             }
12 
13             set
14             {
15                 _name = value;
16             }
17         }
18 
19         public int Age
20         {
21             get
22             {
23                 return _age;
24             }
25 
26             set
27             {
28                 _age = value;
29             }
30         }
31     }
32 
33     class Program
34     {
35         static void Main(string[] args)
36         {
37             Person p = new Person();
38             p.Name = "ZhangSan";
39             p.Age = 20;
40 
41             using (FileStream fsWrite = new FileStream(@"C:UsersadminDesktopSerializable.txt", FileMode.OpenOrCreate, FileAccess.Write))
42             {
43                 BinaryFormatter bf = new BinaryFormatter();
44                 bf.Serialize(fsWrite, p);
45             }
46             Console.WriteLine("Serialize Success");
47             Console.ReadKey();
48 
49             //using (FileStream fsRead = new FileStream(@"C:UsersadminDesktopSerializable.txt", FileMode.OpenOrCreate, FileAccess.Read))
50             //{
51             //    BinaryFormatter bf = new BinaryFormatter();
52             //    Person pObj = (Person)bf.Deserialize(fsRead);
53             //}
54         }
55     }
序列化与发序列化

3.9:部分类 partial

3.10:密封类 sealed 不能被继承, 可以继承别的普通类

ToString(); 是Object的虚方法,子类可以重写父类的虚方法

3.11:接口

[public] interface I..able

{

  成员;

}

不允许写具有方法体的函数,不允许有字段,接口中允许有自动属性

------------------------------------------------------------------

接口是一种规范

1:只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员

2:接口中的成员不能加"访问修饰符",接口中的成员访问修饰符为public,不能修改。

3:接口中只能有方法,属性,索引器,事件,不能有"字段"和构造函数。

4:接口与接口之间可以继承,并且可以多继承。

5:接口并不能去继承一个类,而类可以继承接口(接口只能继承于接口,而类既可以继承接口,也可以继承类)

6:实现接口的子类必须实现该接口的全部成员。

7:一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并且实现了接口IA,那么语法上A必须写在IA的前面。

8:class MyClass:A,IA {} 因为类是单继承的。

9:显示实现接口的目的:解决方法的重名问题

   什么时候显示的去实现接口:当继承的接口中的方法和参数一模一样的时候,要使用显示的接口。

10:当一个抽象类实现接口的时候,需要子类去实现接口。

Ps: 面试题:C#中的接口和类有什么异同。 

不同点:

不能直接实例化接口。

接口不包含方法的实现。

接口可以多继承,类只能单继承。

类定义可在不同的源文件之间进行拆分。

相同点:

接口、类和结构都可以从多个接口继承。

接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。

接口和类都可以包含事件、索引器、方法和属性。

基础知识:接口只能定义方法(只能定义行为,不能定义实现也就是字段),因为事件、索引器、属性本质上都是方法,所以接口中也可以定义事件、索引器、属性。

Ps:面试题:abstract class和interface有什么区别? 

相同点: 

都不能被直接实例化,都可以通过继承实现其抽象方法。 

不同点: 

接口支持多继承;抽象类不能实现多继承。 

接口只能定义行为;抽象类既可以定义行为,还可能提供实现。 

接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法;

抽象类可以定义字段、属性、包含有实现的方法。  

接口可以作用于值类型(Struct)和引用类型(Class);抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。

补充回答:讲设计模式的时候SettingsProvider的例子。

 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)