C#中的继承

来源:互联网 发布:长沙网络推广营销公司 编辑:程序博客网 时间:2024/04/29 21:15

原文地址:http://www.dingos.cn/index.php?topic=1078.0


继承:将新类作为另一个类的后代来声明和使用、避免重复编写代码、提供代码重用的巨大好处。
有两种继承类型
  • 单一继承
  • 多重继承
C#只支持单一继承,不支持多重继承

【继承】
在C#中,一个类可以基础另一个类。被继承的类称为父类或者基类,继承其他类的类称为子类或派生类。
继承是面向对象编程中一个非常重要的特性。在有继承关系的两个类中,子类不仅具有自己独有的成员,还具有父类的成员。
继承关系在类图中表示为一个箭头,箭头指向的是父类。
继承要符合is-a的关系,即子类是父类。
这是通过以下方式实现的:在声明类时,在类名称后放置一个冒号,然后在冒号后指定要从中继承的类(即基类)。
public class A{
    public A() { }
}

public class B : A{
    public B() { }
}
新类(即派生类)将获取基类的所有非私有数据和行为以及新类为自己定义的所有其他数据或行为。因此,新类具有两个有效类型:新类的类型和它继承的类的类型。
在上面的示例中,类 B 既是有效的 B,又是有效的 A。访问 B 对象时,可以使用强制转换操作将其转换为 A 对象。强制转换不会更改 B 对象,但您的 B 对象视图将限制为 A 的数据和行为。将 B 强制转换为 A 后,可以将该 A 重新强制转换为 B。并非 A 的所有实例都可强制转换为 B,只有实际上是 B 的实例的那些实例才可以强制转换为 B。如果将类 B 作为 B 类型访问,则可以同时获得类 A 和类 B 的数据和行为。对象可以表示多个类型的能力称为多态性。

注意:
★ 没有“:”,默认父类为Object
★ 只能有一个父类,即单继承
★ 子类继承父类的全部成员

【示例】
using System;

class CharacterVal{
    public int setCharVal(char ch){
        char charVal=ch;
        Console.WriteLine("输入的字符是:{0}",charVal);
        return(0);
    }
}

class StringVal : CharacterVal{
    public string strVal;

    public int setStrVal(string str){
        strVal=str;
        Console.WriteLine("输入的字符串是:{0}",strVal);
        return(0);
    }
}

class Inheritance{
    static void Main(){
        StringVal object1 = new StringVal();
        Object1.setCharVal('j');
        Object1.setStrVal("enjoy");
    }
}
【输出结果】
输入的字符是:j
输出的结果是:enjoy

【base关键字】
基类访问只能在构造函数、实例方法或实例属性访问器中进行。
从静态方法中使用 base 关键字是错误的。
base 关键字用于从派生类中访问基类的成员:
  • 调用基类上已被其他方法重写的方法。
  • 指定创建派生类实例时应调用的基类构造函数。
  • 基类访问只能在构造函数、实例方法或实例属性访问器中进行。
  • 从静态方法中使用 base 关键字是错误的。

【base调用父类构造方法】
public class BaseClass {
    public BaseClass() {
        Console.WriteLine("in BaseClass()");
    }
    public BaseClass(int i) {
        Console.WriteLine("in BaseClass(int i)");
    }
}
public class DerivedClass : BaseClass {
    public DerivedClass() : base() { }
    public DerivedClass(int i) : base(i) { }
}

【base调用父类的方法】
public class Person { 
    protected string name = "John L. Malgraine";
    public virtual void GetInfo(){
        Console.WriteLine("Name: {0}", name);
    }
}
class Employee : Person {
    public string id = "ABC567EFG";
    public override void GetInfo() {
        base.GetInfo();
        Console.WriteLine("Employee ID: {0}", id);
    }

【编写子类构造函数的注意实现】
在C#中,一个子类继承父类,在编写子类的构造函数时需要注意以下两点:
1. 隐式调用父类构造函数
如果子类的构造函数没有使用base关键字指明调用父类的那个构造函数,则父类必须提供一个默认的无参构造函数。因为子类构造函数在这种情况下会隐式调用父类的默认无参构造函数base()。
2. 显示调用父类的构造函数
如果父类中没有提供默认的无参构造函数,那么子类的构造函数必须明确指明调用的是那个父类的有参构造函数。
注意:子类的无参构造函数调用父类的有参构造函数时,要给参数赋值。

【继承的特性】
1. 继承的传递性:类可以传递继承即(父类A,子类B继承父类A,子类C继承类B - 即类C直接继承至类B间接基础至类A)。在程序中可以调用父类的方法,也可以是调用父类的父类的方法。
2. 继承的单根性:在C#中明确规定,一个子类不同同时继承多个父类。
3. 密封类:在C#中还有一个特殊的关键字sealed,用它修饰的类是不能被继承的。称为密封类。

【继承的价值】
  • 继承模拟了显示世界的关系,OOP中强调一切皆对象,符号面向对象编程的思考方向。
  • 继承实现了代码重用,合理的使用继承,会使代码更加简洁。
  • 继承使得程序结构清晰,子类和父类的层次结构清晰,最终的目的是使子类只关注子类的相关行为和状态,无须关注父类的行为和状态。

【子类的产生和消亡】
  • 在创建子类的实例时,先创建父类的实例,即先调用父类的构造方法。
  • 在子类结束时,先消亡子类的实例,后消亡父类的实例,即先调用子类的析构方法后调用父类的析构方法。
class First {
    ~First() {
        Console.WriteLine("First");
    }
}
class Second: First {
    ~Second() {
        Console.WriteLine("Second");
    }
}
class TestDestructors {
    static void Main() {
        Second s = new Second ();
    }
}

【里氏替换原则】
原则上子类对象是可以赋给父类对象的,也可以说子类可以替换父类并且出现在父类能够出现的任何地方。但是反过来,父类对象是不能替换子类的。这种特性称为“里氏替换原则(LSP)”。通俗理解就是,父类的方法都要在子类中实现或重写。

里氏替换原则两个关键技术:
1. is操作符的使用
“is”操作符用于检查对象是否与给定类型兼容。
if (obj is string){ }
注意:
如果所提供的表达式非空,并且所提供的对象可以强制转换为所提供的类型而不会导致引发异常,则 is 表达式的计算结果将是 true。
如果已知表达式将始终是 true 或始终是 false,则 is 关键字将导致编译时警告,但是,通常在运行时才计算类型兼容性。
不能重载 is 运算符。
请注意,is 运算符只考虑引用转换、装箱转换和取消装箱转换。不考虑其他转换,如用户定义的转换。
在 is 运算符的左侧不允许使用匿名方法。lambda 表达式属于例外。

2. as操作符的使用
as 运算符用于在兼容的引用类型之间执行转换。
string s = someObject as string;
if (s != null){
    // someObject is a string.
}
as 运算符类似于强制转换操作。但是,如果无法进行转换,则 as 返回 null 而非引发异常。
expression as type
等价与
expression is type ? (type)expression : (type)null
注意,as 运算符只执行引用转换和装箱转换。as 运算符无法执行其他转换,如用户定义的转换,这类转换应使用强制转换表达式来执行。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 cad填充图案太密怎么办 桃木葫芦挂件裂口了怎么办 皮肤被太阳晒伤变黑怎么办 皮肤又粗又黑该怎么办 盆栽红薯长疯了怎么办 四叶草叶子发黄怎么办 美篇不想让别人看到怎么办 黑魂3暗灵入侵怎么办 问道手游账号忘了怎么办 问道手游密码忘了怎么办 毒蚂蚁咬了红肿怎么办 电脑开机后有电流声怎么办 小学生阅读方面不会总结怎么办 天龙八部手游转职装备怎么办 投简历没回应该怎么办? 开车开的腰疼怎么办 开车腰疼怎么办吃什么 58简历投错了怎么办 开了一天车腰疼怎么办 开车腰疼怎么办怎么解决好 球球大作战找不到主界面怎么办 在QQ上找不到主界面怎么办 mac地址被过滤了怎么办 续贷声明含非法字符怎么办 辞职老板不给结工资怎么办 辞职后老板不发工资怎么办 联想手机不自带系统升级怎么办 苹果6玩崩坏3卡怎么办 机票名字打错了怎么办? 安装软件后显示名字乱码怎么办 户口上民族错了怎么办 改名字后行驶证怎么办 眼角撞到了肿了怎么办 想不想修真邪气怎么办 进户门比房间门低怎么办 吃了药反胃想吐怎么办 药吃了胃难受怎么办 吃了牙痛药胃痛怎么办 吃了药刺激胃怎么办 吃凉的刺激到胃怎么办 误食打农药的菜怎么办