簡體   English   中英

C# inheritance 問題

[英]C# inheritance questions

我正在創建一個抽象基礎 class ,它具有由其他類實現的功能。 我的疑惑如下

1)我是否需要在每個需要被子類覆蓋的 function 前面給出“虛擬”? 我看到一些沒有 virtual 關鍵字的示例,它們仍然可以被覆蓋。

2)我需要一個 function 將在基礎 class 中實現,我不希望它被子類覆蓋。 我在 function 前面添加了“固定”關鍵字。 編譯器開始抱怨“成員”不能被密封,因為它不是覆蓋。 我在這里做錯了嗎?

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;
        }


    };
  1. 對於在抽象 class 中沒有實現的方法,也使用abstract

     abstract public void Draw(); abstract public float getWidth(); abstract public void Swap(); abstract public void Erase();
  2. 默認情況下方法是不可覆蓋的; 它們只允許在聲明為abstractvirtualoverride時覆蓋派生類(但不允許override sealed )。

    因此,除了public之外,您不需要給getShapeDetails()任何其他修飾符:

     public ShapeDetails getShapeDetails() { return _shapedDetails; }

附帶說明一下,您應該堅持 .NET 命名約定並使用 Pascal 大小寫大寫方法名稱,因此getWidth()變為GetWidth()並且getShapeDetails()變為GetShapeDetails()

實際上,您應該為_shapedDetails字段使用屬性獲取器,而不是getShapeDetails()方法:

private ShapeDetails _shapedDetails;

public ShapeDetails ShapedDetails
{
    get { return _shapedDetails; }
}

要被覆蓋,必須將成員標記為虛擬或抽象。 如果是抽象的,則 class 也必須是抽象的,並且該成員在定義的 class 中沒有實現。 虛擬成員必須提供實現。 派生類必須覆蓋抽象成員並且可以覆蓋虛擬成員。 非虛擬成員可能不會被“密封”,因為它們無論如何都不能被覆蓋。

第 1 點:您可以將這些函數抽象為虛擬函數,而不是虛擬函數。

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

這意味着必須覆蓋那些 function。 目前,您可以在沒有任何定義的情況下創建抽象 class 的子類,它仍然可以編譯。 通過說這些是必須被覆蓋的抽象函數。 如果您不覆蓋,則子 class 也將是抽象的。

關於第2點:您可以添加使用固定詞的代碼嗎?

1-引用覆蓋(C# 參考)

您不能覆蓋非虛擬或 static 方法。 被覆蓋的基方法必須是虛擬的、抽象的或覆蓋的。


2-引用密封(C# 參考)

您還可以在覆蓋基礎 class 中的虛擬方法或屬性的方法或屬性上使用密封修飾符。 這使您能夠允許類從 class 派生,並防止它們覆蓋特定的虛擬方法或屬性。

如果是抽象方法,默認為虛方法,需要在繼承class中實現。 否則,如果它不是抽象的,你需要有 virtual 關鍵字。 如果您不這樣做,將使用編譯時類型方法。

只能重寫虛方法,只能實現抽象方法(如接口方法)。 否則,唯一能做的就是聲明一種新方法來“隱藏”舊方法,如下所示:

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
        }
    }
}
  1. 如果你想在你的基礎 class 中提供一個可以在派生類中被覆蓋的默認實現,你可以用virtual鍵標記 function; 或者您可以將其標記為abstract ,將實現委托給派生類。
  2. 如果您希望 function 不在子實現中被覆蓋,請不要將其標記為virtualabstract :只需像往常一樣定義 function 即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM