2011-05-25 204 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:簡單地定義函數就像你正常做的那樣。