C#继承问题

时间:2011-05-25 07:27:08

标签: c# .net oop inheritance

我正在创建一个抽象基类,其中包含由其他类实现的函数。我的怀疑如下

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


    };

7 个答案:

答案 0 :(得分:9)

  1. 对于在抽象类中没有实现的方法,也可以使用abstract

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

    因此,除了getShapeDetails()之外,您无需提供public任何其他修饰符:

    public ShapeDetails getShapeDetails()
    {
        return _shapedDetails;
    }
    

  3. 另外,您应该坚持使用.NET命名约定并使用Pascal大小写方法名称,因此getWidth()变为GetWidth()getShapeDetails()变为GetShapeDetails()。< / p>

    事实上,您应该使用property getter来代替_shapedDetails字段:

    getShapeDetails()

答案 1 :(得分:1)

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

答案 2 :(得分:1)

第1点:代替虚拟,你可以将这些功能抽象化。

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

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

关于第2点:你能添加使用固定字的代码吗?

答案 3 :(得分:1)

1-参考override (C# Reference)

  

您无法覆盖非虚拟或   静态方法。被覆盖的基地   方法必须是虚拟的,抽象的或   覆盖。


2-参考sealed (C# Reference)

  

您也可以使用密封修改器   在覆盖的方法或属性上   基础中的虚拟方法或属性   类。这使您可以允许   从你的班级派生的班级   防止他们压倒特定的   虚拟方法或属性。

答案 4 :(得分:0)

如果是抽象方法,则该方法默认为virtual,需要在继承类中实现。 否则,如果它不是抽象的,则需要使用virtual关键字。如果不这样,将使用编译时类型方法。

答案 5 :(得分: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
        }
    }
}

答案 6 :(得分:0)

  1. 如果要在基类中提供可在派生类中重写的默认实现,则可以使用virtual关键字标记该函数;或者您可以将其标记为abstract,将实现委派给派生类。
  2. 如果您希望在子实现中不要覆盖函数,请不要将其标记为virtualabstract:只需像正常情况一样定义函数。