首页 > 开发 > 综合 > 正文

深入剖析C#继承机制4

2024-07-21 02:18:13
字体:
来源:转载
供稿:网友
2) 隐藏基类成员

  想想看,如果所有的类都可以被继承,继承的滥用会带来什么后果?类的层次结构体系将变得十分庞,大类之间的关系杂乱无章,对类的理解和使用都会变得十分困难。有时候,我们并不希望自己编写的类被继承。另一些时候,有的类已经没有再被继承的必要。c#提出了一个密封类(sealed class)的概念,帮助开发人员来解决这一问题。

  密封类在声明中使用sealed 修饰符,这样就可以防止该类被其它类继承。如果试图将一个密封类作为其它类的基类,c#将提示出错。理所当然,密封类不能同时又是抽象类,因为抽象总是希望被继承的。

  在哪些场合下使用密封类呢?密封类可以阻止其它程序员在无意中继承该类。而且密封类可以起到运行时优化的效果。实际上,密封类中不可能有派生类。如果密封类实例中存在虚成员函数,该成员函数可以转化为非虚的,函数修饰符virtual 不再生效。

  让我们看下面的例子:


bstract class a
{
public abstract void f( ) ;
}
sealed class b: a
{
public override void f( )
{ // f 的具体实现代码 }
}

  如果我们尝试写下面的代码

class c: b{ }

  c#会指出这个错误,告诉你b 是一个密封类,不能试图从b 中派生任何类。

  (3) 密封方法

  我们已经知道,使用密封类可以防止对类的继承。c#还提出了密封方法(sealedmethod) 的概念,以防止在方法所在类的派生类中对该方法的重载。对方法可以使用sealed 修饰符,这时我们称该方法是一个密封方法。

  不是类的每个成员方法都可以作为密封方法密封方法,必须对基类的虚方法进行重载,提供具体的实现方法。所以,在方法的声明中,sealed 修饰符总是和override 修饰符同时使用。请看下面的例子代码:


using system ;
class a
{
public virtual void f( )
{ console.writeline("a.f") ; }
public virtual void g( )
{ console.writeline("a.g") ; }
}
class b: a
{
sealed override public void f( )
{ console.writeline("b.f") ; }
override public void g( )
{ console.writeline("b.g") ; }
}
class c: b
{
override public void g( )
{ console.writeline("c.g") ; }
}

  类b 对基类a 中的两个虚方法均进行了重载,其中f 方法使用了sealed 修饰符,成为一个密封方法。g 方法不是密封方法,所以在b 的派生类c 中,可以重载方法g,但不能重载方法f。

  (4) 使用 new 修饰符隐藏基类成员

  使用 new 修饰符可以显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。

  请看下面的类:


public class mybase
{
public int x ;
public void myvoke() ;
}

  在派生类中用 myvoke名称声明成员会隐藏基类中的 myvoke方法,即:


public class myderived : mybase
{ new public void myvoke (); }

  但是,因为字段 x 不是通过类似名隐藏的,所以不会影响该字段。

  通过继承隐藏名称采用下列形式之一:

   a、引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。

   b、引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。同时也隐藏具有相同签名的所有基类方法。

   c、引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。

  注意:在同一成员上同时使用 new 和 override 是错误的。同时使用 new 和 virtual 可保证一个新的专用化点。在不隐藏继承成员的声明中使用 new 修饰符将发出警告。

  示例1:在该例中,基类 mybasec 和派生类 myderivedc 使用相同的字段名 x,从而隐藏了继承字段的值。该例说明了 new 修饰符的使用。同时也说明了如何使用完全限定名访问基类的隐藏成员。


using system ;
public class mybase
{
public static int x = 55 ;
public static int y = 22 ;
}
public class myderived : mybase
{
new public static int x = 100; // 利用new 隐藏基类的x
public static void main()
{
// 打印x:
console.writeline(x);
//访问隐藏基类的 x:
console.writeline(mybase.x);
//打印不隐藏的y:
console.writeline(y);
}
}

  输出: 100 55 22

  如果移除 new 修饰符,程序将继续编译和运行,但您会收到以下警告:

the keyword new is required on 'myderivedc.x' because it hides inherited member 'mybasec.x'.

  如果嵌套类型正在隐藏另一种类型,如下例所示,也可以使用 new 修饰符修改此嵌套类型。




商业源码热门下载www.html.org.cn

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表