2011-05-25 166 views
6

我正在创建一个具有其他类实现的函数的抽象基类。我的疑惑如下C#继承问题

1)我需要在每个需要被子类覆盖的函数前给'虚拟'吗?我看到一些没有虚拟关键字的例子,仍然可以被覆盖。

2)我需要一个将在基类中实现的函数,我不希望它被子类覆盖。我添加了该功能的“固定”关键字。编译器开始抱怨“成员”不能被密封,因为它不是一个覆盖。我在这里做错了什么?

abstract public class ShapeBase 
    { 
     private ShapeDetails _shapedDetails; 

     public CampusCardBase(ShapeDetails shDetails) 
     { 
      _shapedDetails= shDetails; 
     } 

     public virtual void Draw(); 
     public virtual float getWidth(); 
     public virtual void Swap(); 
     public virtual void Erase(); 

     public sealed ShapeDetails getShapeDetails() 
     { 
      return _shapedDetails; 
     } 


    }; 
+2

你错过了那些方法上的'abstract'关键字...如果你不想重写但是实现然后使用abstract。 – 2011-05-25 07:31:12

回答

9
  1. 对于一个抽象类没有实现的方法,使用abstract以及:

    abstract public void Draw(); 
    abstract public float getWidth(); 
    abstract public void Swap(); 
    abstract public void Erase(); 
    
  2. 方法没有重写的默认;它们只允许派生类覆盖,如果声明abstract,virtualoverride(但不是override sealed)。

    因此你不需要给getShapeDetails()任何其他修饰比public

    public ShapeDetails getShapeDetails() 
    { 
        return _shapedDetails; 
    } 
    

在一个侧面说明,你应该坚持使用.NET命名约定,用大写方法名称帕斯卡情况,所以getWidth()变为GetWidth()getShapeDetails()变成GetShapeDetails()

事实上,你应该使用一个property吸气您_shapedDetails领域,而不是getShapeDetails()方法:

private ShapeDetails _shapedDetails; 

public ShapeDetails ShapedDetails 
{ 
    get { return _shapedDetails; } 
} 
+5

“密封关键字仅适用于类声明,而不适用于方法声明” - 它可以适用于方法:“覆盖密码”覆盖虚拟/抽象方法并阻止下游覆盖。 – Ani 2011-05-25 07:34:54

+0

-1:如果成员覆盖虚拟或抽象成员,则成员可以被密封。 – phoog 2011-05-25 07:35:38

+0

@BoltClock - 实际上,可以在类和成员上使用sealed关键字来防止进一步派生。在OP的问题中,这不是期望的行为,但它在某些边缘情况下实际上非常有用,可以封闭不应在更多派生类中重写的虚拟方法。其余的答案+1,我相信这是解决原来的问题。 – 2011-05-25 07:36:56

1

要覆写投放,成员必须标明虚拟的或抽象的。如果是抽象的,则该类也必须是抽象的,并且该成员在定义类中没有实现。虚拟成员必须提供实施。派生类必须重写抽象成员并可以重写虚拟成员。非虚拟成员可能不会被“密封”,因为它们无论如何都不能被覆盖。

0

如果是抽象方法,该方法默认是虚拟的,需要在继承类中实现。 否则,如果它不是抽象的,你需要有虚拟关键字。如果你不使用编译时类型的方法。

+0

-1:默认情况下,抽象类的成员不是抽象的;他们必须用“抽象”关键字标记为抽象。 – phoog 2011-05-25 07:38:40

+0

我的意思是方法,抱歉编辑了这个帖子:-) – MBen 2011-05-25 07:43:04

+0

现在已经很清楚了。不幸的是,即使您在我投票之后似乎编辑了答案,SO也不会让我删除我的投票。:( – phoog 2011-05-25 07:52:52

1

第1点:而不是虚拟,你可以使这些功能抽象。

public abstract void Draw(); 
public abstract float getWidth(); 
public abstract void Swap(); 
public abstract void Erase(); 

这意味着这些函数必须被覆盖。目前,您可以创建抽象类的子类,而不需要任何定义,它仍然可以编译。通过说这些是抽象函数必须被覆盖。如果你不重写,那么子类也将是抽象的。

而关于第2点:你可以添加固定词的代码吗?

1

1-指的override (C# Reference)

不能覆盖的非虚拟或 静态方法。被覆盖的方法 方法必须是虚拟的,抽象的或覆盖。


2-指的sealed (C# Reference)

还可以使用密封的改性剂 上重写 虚拟方法或属性在碱 类的方法或属性。这使您可以允许 类从您的类派生,并且允许 阻止它们覆盖特定的虚拟方法或属性。

0

只有一个虚拟方法可以被重写,并且只能实现一个抽象方法(如接口方法)。否则,只有一个人能做的就是声明一个新的方法来“隐藏”旧如下:

new public void getShapeDetails() { 
    // Hides base.getShapeDetails(); 
} 

下面是一个代码示例/解释。

//----------------------------------------------------------------------------- 
// <copyright file="Program.cs" company="DCOM Productions"> 
//  Copyright (c) DCOM Productions. All rights reserved. 
// </copyright> 
//----------------------------------------------------------------------------- 

namespace AbstractClassExample { 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 

    class Program { 
     /// <summary> 
     /// Example abstract base class 
     /// </summary> 
     public abstract class FooClass { 

      /// <summary> 
      /// Abstract Method 
      /// </summary> 
      public abstract void abstractFoo(); 

      /// <summary> 
      /// Virtual Method 
      /// </summary> 
      public virtual void virtualFoo() { 
       // Todo 
      } 

      /// <summary> 
      /// Normal Method 
      /// </summary> 
      public void Foo() { 
       // Todo 
      } 

     } 

     public class FooDeriver : FooClass { 
      /// <summary> 
      /// Implements base.abstractFoo 
      /// </summary> 
      public override void abstractFoo() { 
       throw new NotImplementedException(); 
      } 

      /// <summary> 
      /// Overrides base.virtualFoo 
      /// </summary> 
      public override void virtualFoo() { 
       base.virtualFoo(); 
      } 

      /// <summary> 
      /// Compiler ErrorError 1 
      /// cannot override inherited member 'ConsoleApplication1.Program.FooClass.Foo()' because it is not marked virtual, abstract, or override 
      /// </summary> 
      public override void Foo() { 
       throw new NotImplementedException(); 
      } 
     } 

     static void Main(string[] args) { 
      // Program code 
     } 
    } 
} 
0
  1. 如果你要提供你的基类的默认实现,可以在派生类中重写您可以标记与virtual keywork功能;也可以将其标记为abstract,将实现委托给派生类。
  2. 如果你想要一个函数不会在子实现中被忽略,不要把它标记为virtualabstract:简单地定义函数就像你正常做的那样。