5.1类继承(继承的优点就不更多的赘述,在这里主要说他的用法)
通过继承可以定义一个新类,新类纳入一个已经声明的类并进行扩展。
可以使用一个已经存在的类作为新类的基础。已存在的类称为基类(base class),新类称为派生类(derived class)。派生类成员的组成如下:
(1)本身声明中的成员;
(2)基类的成员。
要声明一个派生类,需要在类名后加入基类规格说明。基类规格说明由冒号和用作基类的类名称组成。派生类直接继承自列出的基类。
(1)派生类扩展它的基类,因为它包含了基类的成员,还有它本身声明中的新增功能。
(2)派生类不能删除它所继承的任何成员。
例如,下面展示了名为 OtherClass 的类的声明,它继承自名为SomeClass的类:
class OtherClass : SomeClass //基类规格说明
{
....
}
5.2访问继承的成员
using System;
class SomeClass//基类
{
public string Field1 = "base class field";
public void Method1(string value)
{
Console.WriteLine($"Base class--Methodi:{value}");
}
}
class OtherClass : SomeClass
{//派生类
public string Field2="derived class field";
public void Method2(string value)
{
Console.WriteLine($"Derived class--Method 2:{value}");
}
}
class Program
{
static void Main()
{
OtherClass oc = new OtherClass();
oc.Method1(oc.Field1);//以基类字段为参数的基类方法,
oc.Method1(oc.Field2);//以派生字段为参数的基类方法
oc.Method2(oc.Field1);//以基类字段为参数的派生方法
oc.Method2(oc.Field2);//以派生字段为参数的派生方法
}
}
5.3屏蔽基类的成员
虽然派生类不能删除它继承的任何成员,但可以用与基类成员名称相同的成员来屏蔽(mask)基类成员。这是继承的主要功能之一,非常实用。
例如,我们要继承包含某个特殊方法的基类。该方法虽然适合声明它的类,但不一定适合派生类。在这种情况下,我们希望在派生类中声明新成员以屏蔽基类中的方法。在派生类中屏蔽基类成员的一些要点如下。
(1)要屏蔽一个继承的数据成员,需要声明一个新的相同类型的成员,并使用相同的名称。
(2)通过在派生类中声明新的带有相同签名的函数成员,可以屏蔽继承的函数成员。请记住,签名由名称和参数列表组成,不包括返回类型。
(3)要让编译器知道你在故意屏蔽继承的成员,可使用new修饰符。否则,程序可以成功编译,但编译器会警告你隐藏了一个继承的成员。
(4)也可以屏蔽静态成员。
(5)使用new关键字以显式地告诉编译器屏蔽基类成员。
代码展示:
using System;
class SomeClass//基类
{
public string Field1 = "SomeClass Field1";
public void Method1(string value)
{
Console.WriteLine($"SomeClass.Method1:{value}");
}
}
class OtherClass : SomeClass//派生类
{
new public string Field1 = "OtherClass Field1";//屏蔽基类成员
new public void Method1(string value)//屏蔽基类成员
{
Console.WriteLine($"OtherClass.Method1:{value}"); }
}
class Program
{
static void Main()
{
OtherClass oc = new OtherClass();//使用屏蔽成员
oc.Method1(oc.Field1);//使用屏蔽成员
}
}
运行结果:
5.4访问基类的成员
如果派生类必须访问被隐藏的继承成员,可以使用基类访问表达式。基类访问表达式由关键字base后面跟着一个点和成员的名称组成,如下所示:
Console. WriteLine("{0}", base. Field 1);
基类访问代码:
在下面的代码中,派生类 OtherClass 隐藏了基类中的Field1,但可以使用基类访问表达式访问它。
using System;
class SomeClass
{
public string Field1 ="Field1--In the base class";
}
class OtherClass : SomeClass
{//派生类
new public string Field1="Field1--In the derived class";
public void PrintField1()
{
Console.WriteLine(Field1);//访问派生类Console. Writeline(base. Field 1);//访问基类
}
}
class Program
{
static void Main()
{
OtherClass oc = new OtherClass();
oc.PrintField1();
}
}
5.5虚方法与覆写方法
5.5.1在开始之前首先介绍一些使用基类的引用的知识
派生类的实例由基类的实例和派生类的新增成员组成。派生类的引用指向整个类的对象(包括基类部分)
如果有一个派生类对象的引用,就可以获取该对象基类部分的引用(使用类型转换运算得该引用转换为基类类型)。类型转换运算符放置在对象引用的前面,由圆括号括起的要被转换的类名组成。类型转换将在以后阐述。将派生类对象强制转换为基类对象的作用是产生的量只能访问基类的成员(在被覆写方法中除外,稍后会讨论)。
这里直接看下面的代码
using System;
class MyBaseClass
{
public void Print()
{
Console.WriteLine("This is the base class.");
}
}
class MyDerivedClass : MyBaseClass
{
public int var1;
new public void Print()
{
Console.WriteLine("This is derived class");
}
}
class Program
{
static void Main()
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived;
derived.Print();
mybc.Print();
//mybc.var1 = 1;//错误基类的引用无法访问派生类成员
}
}
运行结果:、
5.5.2虚方法与覆写
其实,虚方法与覆写就相当于给一个机会给派生类去实现:比如说你有一个动物类,作为你的基类,它其中有一个方法是睡眠,你以动物类为基类派生了一个狮子类,狮子类的睡眠就与动物类的睡眠方法一致,就不用在派生类中再重新书写睡眠这个方法。而你写一个蛇类作为动物类的派生,我们知道蛇类的睡眠肯定与动物类的有所区别,因为蛇在冬天要冬眠。在这样的情况下。我们就可以运用虚方法与腹泻方法,有助于程序的可读性
当使用基类引用访问派生类对象时,得到的是基类的成员。虚方法可以使基类的引用访问“升至”派生类内。
可以使用基类引用调用派生类的方法,只需满足下面的条件。
(1)派生类的方法和基类的方法有相同的签名和返回类型。
(2)基类的方法使用virtual标注。
(3)派生类的方法使用override标注。
代码示例:
using System;
class MyBaseClass
{
virtual public void Print()
{
Console.WriteLine("This is the base class.");
}
}
class MyDerivedClass : MyBaseClass
{
public int var1;
override public void Print()
{
Console.WriteLine("This is derived class");
}
}
class Program
{
static void Main()
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = new MyBaseClass();
derived.Print();
mybc.Print();
}
}
运行结果:
using System;
class MyBaseClass
{
virtual public void Print()
{
Console.WriteLine("This is the base class.");
}
}
class MyDerivedClass : MyBaseClass
{
public int var1;
override public void Print()
{
Console.WriteLine("This is derived class");
}
}
class Program
{
static void Main()
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass mybc = (MyBaseClass)derived;
derived.Print();
mybc.Print();
}
}
运行结果:
virtual和override方法代码说明:
注意和上一种情况(用new隐藏基类成员)相比在行为上的区别。
当使用基类引用(mybc)调用Print方法时,方法调用被传递到派生类并执行,因为:基类的方法被标记为virtual;在派生类中有匹配的override方法。
覆写方法可以在继承的任何层次出现:
当使用对象基类部分的引用调用一个被覆写的方法时,方法的调用被沿派生层次上溯执行,一直到标记为override的方法的最高派生(most-derived)版本。如果在更高的派生级别有该方法的其他声明,但没有被标记为override,那么它们不会8被调用。
5.6构造函数的执行顺序
这一块不详细介绍有需要可以看看别人写的(我感觉自己才疏学浅,写出来的东西生涩难弄不如去看看别人写的)
http://t.zoukankan.com/TJessica-p-6366066.html
5.7成员访问修饰符
这部分基本是纯定义部分直接贴图(C#图解教程)QWQ其实是自己懒
5.8抽象类
5.8.1抽象成员
抽象成员是指设计为被覆写的函数成员。抽象成员有以下特征。
(1)必须是一个函数成员。也就是说,字段和常量不能为抽象成员。
(2)必须用abstract修饰符标记。
(3)不能有实现代码块。抽象成员的代码用分号表示。
例如、下面取自一个类定义的代码声明了两个抽象成员:一个名为 PrintStuff 的抽象方法和一个名为 MyProperty 的抽象属性。注意在实现块位置的分号。
关键字分号替换实现
abstract public void PrintStuff (string s);
abstract public int MyProperty
{
get; 一分号替换实现
set; 一分号替换实现
}
抽象成员只可以在抽象类中声明,下一节中会讨论。一共有4种类型的成员可以声明为抽象的:方法;属性;事件;索引器。
关于抽象成员的其他重要事项如下。
(1)尽管抽象成员必须在派生类中用相应的成员覆写,但不能把 virtual修饰符附加abstract修饰符。
(2)类似于虚成员,派生类中抽象成员的实现必须指定override修饰符
5.8.2抽象类
抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。不能创建抽象类的实例。
抽象类使用abstract修饰符声明。
abstract class MyClass
{
}
抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带实现的成员的任意组合。
抽象类自己可以派生自另一个抽象类。
任何派生自抽象类的类必须使用override关键字实现该类所有的抽象成员,除非派生类自己也是抽象类。
5.9密封类与静态类
密封类:
密封类只能被用作独立的类,它不能被用作基类。
密封类使用sealed修饰符标注。
例如,下面的类是一个密封类。将它用作其他类的基类会产生编译错误。
关键字
sealed class MyClass
{
---
}
静态类:
静态类中所有成员都是静态的。静态类用于存放不受实例数据影响的数据和函数。静态类的一个常见用途可能是创建一个包含一组数学方法和值的数学库。
关于静态类需要了解的重要事项如下。
(1)类本身必须标记为static。
(2)类的所有成员必须是静态的。
(3)类可以有一个静态构造函数,但不能有实例构造函数,因为不能创建该类的实例。口(4)静态类是隐式密封的,也就是说,不能继承静态类。
可以使用类名和成员名,像访问其他静态成员那样访问静态类的成员。从C#6.0开始,也可以通过使用using static指令来访问静态类的成员,而不必使用类名。