C # вопросы наследования - PullRequest
6 голосов
/ 25 мая 2011

Я создаю абстрактный базовый класс, в котором есть функции, реализованные другими классами. Мои сомнения заключаются в следующем

1) Нужно ли давать «virtual» перед каждой функцией, которая должна быть переопределена дочерними классами? Я вижу некоторые примеры без виртуального ключевого слова, и все же они открыты для переопределения.

2) Мне нужно иметь функцию, которая будет реализована в базовом классе, и я не хочу, чтобы она была переопределена дочерними классами. Я добавил «фиксированное» ключевое слово перед этой функцией. Компилятор начинает жаловаться, что 'member' не может быть запечатан, потому что это не переопределение. Я что-то здесь не так делаю?

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 ]

9 голосов
/ 25 мая 2011
  1. Для методов без реализаций в абстрактном классе также используйте abstract:

    abstract public void Draw();
    abstract public float getWidth();
    abstract public void Swap();
    abstract public void Erase();
    
  2. Методы не могут быть переопределены по умолчанию;они позволяют переопределять производные классы только в том случае, если объявлены abstract, virtual или override (но не override sealed).

    Поэтому вам не нужно указывать getShapeDetails() любые другие модификаторы, кроме public:

    public ShapeDetails getShapeDetails()
    {
        return _shapedDetails;
    }
    

В дополнение к этому следует придерживаться соглашений об именах .NET и использовать имена методов с заглавной буквы, используя регистр Pascal, поэтому getWidth() становится GetWidth()и getShapeDetails() становится GetShapeDetails().

Фактически вы должны использовать свойство getter для своего поля _shapedDetails вместо getShapeDetails() метода:

private ShapeDetails _shapedDetails;

public ShapeDetails ShapedDetails
{
    get { return _shapedDetails; }
}
1 голос
/ 25 мая 2011

1- Ссылаясь на переопределение (C # Reference)

Вы не можете переопределить не виртуальный или статический метод. Переопределенная база Метод должен быть виртуальным, абстрактным или переопределить.


2- Ссылается на загерметизировано (C # Reference)

Вы также можете использовать закрытый модификатор на метод или свойство, которое переопределяет виртуальный метод или свойство в базе учебный класс. Это позволяет вам разрешить классы, чтобы извлечь из вашего класса и помешать им переопределить конкретные виртуальные методы или свойства.

1 голос
/ 25 мая 2011

точка 1: вместо виртуальных вы можете сделать эти функции абстрактными.

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

Это означает, что эти функции ДОЛЖНЫ быть переопределены.В настоящее время вы можете создать подкласс вашего абстрактного класса без каких-либо определений, и он все равно будет компилироваться.Говоря, что это абстрактные функции, они должны быть отменены.Если вы не переопределите, то подкласс также будет абстрактным.

А по поводу пункта 2: можете ли вы добавить код, в котором используется фиксированное слово?

1 голос
/ 25 мая 2011

Для переопределения член должен быть помечен как виртуальный или абстрактный. Если абстрактный, класс также должен быть абстрактным, и член не имеет реализации в определяющем классе. Виртуальный член должен предоставить реализацию. Производные классы должны переопределять абстрактные члены и могут переопределять виртуальные члены. Не виртуальные участники не могут быть «запечатаны», потому что они не могут быть переопределены в любом случае.

0 голосов
/ 25 мая 2011
  1. Вы можете пометить функцию с помощью клавиш virtual, если хотите предоставить реализацию по умолчанию в базовом классе, которую можно переопределить в производных классах;или вы можете пометить его как abstract, делегируя реализацию производным классам.
  2. Если вы хотите, чтобы функция НЕ была переопределена в дочерних реализациях, НЕ помечайте ее как virtual или abstract: простоопределите функцию как обычно.
0 голосов
/ 25 мая 2011

Только виртуальный метод может быть переопределен, и только абстрактный метод может быть реализован (как методы интерфейса).В противном случае единственный, кто может сделать это, - объявить новый метод «скрытия» старого, как показано ниже:

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 голосов
/ 25 мая 2011

Если это абстрактный метод, метод по умолчанию является виртуальным и должен быть реализован в наследующем классе.В противном случае, если оно не является абстрактным, вам нужно иметь ключевое слово virtual.Если вы этого не сделаете, будет использован метод типа времени компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...