二、C#图解教程第七章--类和继承
一、类继承
示例:
注意:
1.所有的类都派生自object类
2.C#支支持单继承
3.继承的层次没有限制
屏蔽基类成员
派生类不能删除基类成员,但可以声明和基类相同的成员来屏蔽基类成员
class SomeClass { public string Field1 = "SomeClass--Field1"; public void Mehod1(string value) { Console.WriteLine("SomeClass Method1:{0} ",value); } } 1.不加new关键字 class OtherClass:SomeClass { public string Field1 = "OtherClass--Field1"; public void Mehod1(string value) { Console.WriteLine("OtherClass Method1:{0} ", value); } } 2.关键字new放在访问修饰符后 class OtherClass:SomeClass { public new string Field1 = "OtherClass--Field1"; public new void Mehod1(string value) { Console.WriteLine("OtherClass Method1:{0} ", value); } } 3.关键字new放在访问修饰符前 class OtherClass:SomeClass { new public string Field1 = "OtherClass--Field1"; new public void Mehod1(string value) { Console.WriteLine("OtherClass Method1:{0} ", value); } } static void Main(string[] args) { OtherClass otherclass = new OtherClass(); otherclass.Mehod1(otherclass.Field1); Console.ReadLine(); }
基类访问
如果派生类想访问被隐藏的继承成员,可以使用基类访问表达式
class OtherClass:SomeClass
{
new public string Field1 = "OtherClass--Field1";
new public void Mehod1(string value)
{
Console.WriteLine("OtherClass Method1:{0} ", value);
访问被隐藏的继承成员
Console.WriteLine("SomeClass Method1:{0} ", base.Field1);
}
}
{
new public string Field1 = "OtherClass--Field1";
new public void Mehod1(string value)
{
Console.WriteLine("OtherClass Method1:{0} ", value);
访问被隐藏的继承成员
Console.WriteLine("SomeClass Method1:{0} ", base.Field1);
}
}
使用基类的引用
派生类的实例:基类的实例加上派生类新增的成员。
派生类的引用:指向整个类,包括基类部分的引用。
基类的引用:可以通过强制转换将派生类的引用转为基类的引用。
示例:
static void Main(string[] args)
{
DeriverClass deriverclass = new DeriverClass();
deriverclass.Printf();
BaseClass baseclass=(BaseClass)deriverclass;
baseclass.Printf();
Console.ReadLine();
}
{
DeriverClass deriverclass = new DeriverClass();
deriverclass.Printf();
BaseClass baseclass=(BaseClass)deriverclass;
baseclass.Printf();
Console.ReadLine();
}
class BaseClass
{
public void Printf()
{
Console.WriteLine("This is BaseClass!");
}
}
class DeriverClass:BaseClass
{
new public void Printf()
{
Console.WriteLine("This is DeriverClass!");
}
}
{
public void Printf()
{
Console.WriteLine("This is BaseClass!");
}
}
class DeriverClass:BaseClass
{
new public void Printf()
{
Console.WriteLine("This is DeriverClass!");
}
}
虚方法和复写方法
解决的问题:基类的引用不能访问派生类的对象
示例:
class BaseClass { public void Printf() { Console.WriteLine("This is BaseClass!"); } } class DeriverClass:BaseClass { new public void Printf() { Console.WriteLine("This is DeriverClass!"); } } static void Main(string[] args) { DeriverClass deriverclass = new DeriverClass(); BaseClass baseclass=(BaseClass)deriverclass; baseclass.Printf(); Console.ReadLine(); }
虚方法可以使基类的引用访问派生类的对象
修改以上代码(使用虚方法):
class BaseClass { public virtual void Printf() { Console.WriteLine("This is BaseClass!"); } } class DeriverClass:BaseClass { public override void Printf() { Console.WriteLine("This is DeriverClass!"); } } static void Main(string[] args) { DeriverClass deriverclass = new DeriverClass(); BaseClass baseclass=(BaseClass)deriverclass; baseclass.Printf(); Console.ReadLine(); }
构造函数的执行
构造函数的初始化语句
(1)使用base调用基类的构造函数
public class A { public A(string s1,string s2) { Console.WriteLine("Base class A"+" "+s1+" "+s2); } } public class B:A { string str1; string str2; public B():base("aaa","bbb") { Console.WriteLine("Class B"+" "+str1+" "+str2); } } class Program { static void Main(string[] args) { B b = new B(); Console.ReadLine(); } }
(2)使用this调用当前类的构造函数
public class A { public A() { Console.WriteLine("Base class A"); } } public class B:A { string str1; string str2; public B():this("aaa","bbb") { Console.WriteLine("Class B"+" "+str1+" "+str2); } public B(string s1, string s2) : base() { str1 = s1; str2 = s2; } class Program { static void Main(string[] args) { B b = new B(); Console.ReadLine(); } }
类访问修饰符
程序集间的继承
不同程序集之间的继承时,基类需要在一个程序集中生成dll文件,在另一个程序集中引用这个dll文件,并应用dll文件中的命名空间,方可继承另一个程序集中的类。
成员访问修饰符
静态类
静态类用于存放不受实例影响的数据和函数
(1)静态类必须用static标记
(2)静态类的所有成员必须都是静态的
(3)静态类不能被继承
(4)静态类只有一个静态构造函数
静态类扩展:
(1)静态类可以有静态构造函数,静态构造函数不可以被继承
(2)静态构造函数不可被直接调用,当创建类实例或引用任何静态成员之前,静态构造函数被自动执行,并且
只执行一次。
(3)静态类在内存中是一直有位置的;非静态类在实例化后是在内存中是独立的,它的变量不会重复,在使用后会及时销毁,所以不会出现未知的错误。在C#中静态成员是比较敏感的东西,在不是十分确认的情况下不要使用;
C#的常量
readonly为运行时常量,程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量。
const为编译时常量,程序编译时将对常量值进行解析,并将所有常量引用替换为相应值。
a.声明及初始化
readonly常量只能声明为类字段,支持实例类型或静态类型,可以在声明的同时初始化或者在构造函数中进行初始化,初始化完成后便无法更改。
const常量除了可以声明为类字段之外,还可以声明为方法中的局部常量,默认为静态类型(无需用static修饰,否则将导致编译错误),但必须在声明的同时完成初始化。
b.数据类型支持
由于const常量在编译时将被替换为字面量,使得其取值类型受到了一定限制。const常量只能被赋予数字(整数、浮点数)、字符串以及枚举类型
c.性能比较
const直接以字面量形式参与运算,性能要略高于readonly,但对于一般应用而言,这种性能上的差别可以说是微乎其微。
d.适用场景
在下面两种情况下:
a.取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)
b.对程序性能要求非常苛刻
可以使用const常量,除此之外的其他情况都应该优先采用readonly常量。
扩展方法
扩展方法用于在不修改一个类的代码情况下,为一个类增加一个方法。具体的实现有两种方式,一种是通过创建一个新的示例去调用扩展的方法,另一种是不创建实例,在原来类的基础上调用扩展的方法。
扩展方法的结构: