您的位置:首页 > 其它

继承和多态

2016-03-07 21:53 267 查看
1.虽然构造函数一般定义为公共的,但是派生类从来没有继承父类的构造函数。构造函数只能用于构造定义它的类。

2.sealed关键字:指定该类为密封类,防止作为基类被继承。

3.值类型总是密封的,不能作为基类被继承。所有结构是不能被继承的。

4.在子类构造函数中使用base调用父类的构造函数

 public class T1

        {

            public string Id { get; set; }

            public string Name { get; set; }

            public T1()

            {

            }

            public T1(string id, string name)

            {

                Id = id;

                Name = name;

            }

        }

        public class T2 : T1

        {

            public string FirstName { get; set; }

            public string LastName { get; set; }

            public T2()

            { }

            public T2(string id, string name, string firstName, string lastName)

                : base(id, name)

            {

                FirstName = firstName;

                LastName = lastName;

            }          

        }

5.包含/委托(非Delegate)

代码重用is-a:继承;has-a :包含

public class T3

        {

            T1 t1 = new T1();

            public string GetName()

            {

                return t1.Name;

            }

        }
6.嵌套类型

可以直接在类或这结构的作用域内定义类型(枚举、类、接口、委托),被嵌套的类型(内部的)被认为是嵌套(外部的)类的成员,可以想操作其他成员一样来操作嵌套类型。

通过嵌套类型可以完全控制内部类型的访问级别,可以声明为私有的(通普通成员)。

由于嵌套类型是包含类的成员,所以(通普通成员)可以访问包含类的私有成员。

通常,嵌套类型只用作外部类的辅助方法,而不是为外部类所准备的,如果类型嵌套了另一个类类型,他就可以创建这个类型的成员变量。

7.virtual关键字

如果希望基类定义可以(不是必须)由子类重写的方法,就必须用virtual关键字修饰。

public class T3:T1

        {

            T1 t1 = new T1();            

            public override string Func1(string str1, string str2)

            {

                return t1.Func1(str1, str2);

            }

        }

8.密封虚成员

只希望防止派生类来重写某个方法

public override sealed string Func1(string str1, string str2)

            {

                return t1.Func1(str1, str2);

            }

9.抽象类

尽管我们不能直接创建抽象类的实例,但是在创建其派生类时,仍然会在内存中对其进行组装。因此对抽象类来说,定义若干在分配派生类时间接调用的构造函数是很正常的。

public abstract class BaseClass
{
public int someProperty = 0;
public BaseClass(int property)
{
this.someProperty = property;
}
}

public class ChildClass : BaseClass
{
public ChildClass(int property)
: base(property)
{
}
}

另外,尽管不能创建抽象基类的实例,完全可以使用抽象基类的变量来保存任何子类的引用。


10.成员的遮蔽

如果派生类定义的成员和定义在基类中的成员一致,派生类就遮蔽了父类的版本。可以为派生类的成员添加new关键字,显示的声明派生类型的实现故意设计为隐藏父类的版本。

public new void Draw()

{

//......

}

new 关键字可以应用到任何从基类继承的成员类型中(字段、常量、静态方法、属性等),但是仍然可以通过显示强制转换来访问被遮蔽的基类的成员。

Test t = new Test();

t.Draw(); //new遮蔽了父类的Draw方法,这里调用子类的

((base)t).Draw() ; //这里强制转换为父类,然后调用父类的Draw方法。

11.基类/派生类转换规则

如果两个类是is-a关系,在基类引用中保存派生类的类型总是安全的(隐式转换)。

使用C# 强制转换进行显示的向下转化。

object obj = new T1();

((T1)obj).Id = "1111"; //显示向下转化

12.System.Object

public virtual bool Equals(object obj);//默认情况下,如果被比较的项目,引用对象相同,返回true;

public vitrual string  ToString(); //完全限定名返回对象的字符串表示。

public virtual int  GetHashCode();//返回int值来标识指定的对象实例,默认,使用对象在内存中的当前位置来产生散列值。

如果重写一个类的Equals()方法,我们还需要重写默认的GetHashCode()实现,如果要构建要保存到Hashtable类型中的自定义类型,就应该重写这个成员。System.Collections.Hastable类在内部调用GetHashCode()来获取对象的位置,然后调用Equals()进行精确的匹配。String类已经有完善的散列码算法来使用String的字符数据计算散列值(因此,如果某个类的某个字段可以确保是唯一的,简便的方法就是调用这个字段的GetHanshCode得到散列值)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: