Как скрыть унаследованное свойство в классе без изменения унаследованного класса (базовый класс)?

StackOverflow https://stackoverflow.com/questions/1875401

Вопрос

Если у меня есть следующий пример кода:

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA : ClassBase
{
    public int JustNumber { get; set; }

    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

Что я должен сделать, чтобы скрыть собственность Name (Не показан как член членов класса) без изменения ClassBase ?

Это было полезно?

Решение

Я чувствую запах кода здесь. По моему мнению, вы должны наследовать базовый класс, только если вы реализуете всю функциональность этого базового класса. То, что вы делаете, на самом деле не представляет объектно -ориентированные принципы должным образом. Таким образом, если вы хотите унаследовать от своей базы, вы должны реализовать имя, в противном случае у вас неправильно у вас есть наследство. Ваш класс А должен быть вашим базовым классом, и ваш текущий базовый класс должен наследовать от A, если вы этого хотите, а не наоборот.

Однако, не отклоняться слишком далеко от прямого вопроса. если ты делал Хотите изменить «правила» и хотеть продолжить выбранный вами путь - вот как вы можете сделать это:

Конвенция заключается в том, чтобы внедрить свойство, но бросить NotimplementedException, когда это свойство называется - хотя, мне это тоже не нравится. Но это мое личное мнение, и это не меняет того факта, что эта конвенция все еще стоит.

Если вы пытаетесь установить свойство (и оно объявлено в базовом классе как виртуально), то вы можете либо использовать устаревший атрибут на нем:

[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name 
{ 
    get 
    { 
        return base.Name; 
    }
    set
    {
        base.Name = value;
    }
}

(Редактировать: Как отметил Брайан в комментариях, второй параметр атрибута вызовет ошибку компилятора, если кто -то ссылается на свойство имени, поэтому он не сможет использовать его, даже если вы реализовали ее в производном классе.)

Или, как я упоминал, используйте notimplementedException:

public override string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

Однако, если собственность не объявлен виртуальным, тогда вы можете использовать новое ключевое слово, чтобы заменить его:

public new string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

Вы все еще можете использовать устаревший атрибут так же, как если бы метод был переопределен, или вы можете бросить NotimplementedException, в зависимости от того, что вы выберете. Я бы, наверное, использовал:

[Obsolete("Don't use this", true)]
public override string Name { get; set; }

или же:

[Obsolete("Don't use this", true)]
public new string Name { get; set; }

В зависимости от того, был ли он объявлен виртуальным в базовом классе.

Другие советы

Хотя технически свойство не будет скрыто, один из способов убедительно отговорить его использование - надеть на него атрибуты:

[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]

Это то, что System.windows.forms делает для элементов управления, которые имеют свойства, которые не подходят. А Текст Например, свойство находится под контролем, но оно не имеет смысла на каждом классе, который наследует от контроля. Так в Месяцкалендар, например, текстовое свойство отображается так (согласно источнику справочного материала):

[Browsable(false),
    EditorBrowsable(EditorBrowsableState.Never),
    Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}
  • Browsable - Появляется ли участник в окне свойств
  • Editorbrowable - Появляется ли участник в выпадении Intellisense

Editorbrowable (false) не помешает вам вводить свойство, и если вы используете свойство, ваш проект все равно будет компилироваться. Но поскольку собственность не появляется в Intellisense, не будет так очевидно, что вы можете использовать ее.

Просто скрыть это

 public class ClassBase
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class ClassA : ClassBase
{
    public int JustNumber { get; set; }
    private new string Name { get { return base.Name; } set { base.Name = value; } }
    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = 0;
    }
}

Примечание. Имя по -прежнему будет публичным членом Classbase, учитывая ограничение не изменяя базовый класс, нет никакого способа остановить это.

Зачем насильственно наследовать, когда в этом нет необходимости? Я думаю, что правильный способ сделать это - делать имеет вместо это.

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA
{
    private ClassBase _base;

    public int ID { get { return this._base.ID; } }

    public string JustNumber { get; set; }

    public ClassA()
    {
        this._base = new ClassBase();
        this._base.ID = 0;
        this._base.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

Я полностью согласен с тем, что свойства не должны быть удалены из базовых классов, но иногда вы получаемый класс может иметь другой более подходящий способ ввести значения. Например, в моем случае я наследую от ItemsControl. Как мы все знаем, itemscontrol имеет свойство элементов, но я хочу, чтобы мой контроль объединял данные из 2 источников (например, человека и местоположение). Если бы я ввел пользователь ввести данные, используя элементы, я должен был отделить, а затем рекомбировать значения, поэтому я создал 2 свойства для ввода данных. Но вернемся к первоначальному вопросу, это оставляет элементы, которые я не хочу, чтобы пользователь использовал, потому что я «заменяю» его собственными свойствами. Мне нравятся идеи для просмотра и редактора, но это все еще не мешает пользователю их использовать. Основным моментом здесь является то, что наследование должно сохранять большую часть свойств, но когда есть большой сложный класс (особенно те, где вы не можете изменить исходный код), переписать все было бы очень неэффективным.

Я не думаю, что многие люди, отвечающие здесь, понимают наследство вообще. Существует необходимость наследовать от базового класса и скрыть его некогда публичные функции и функции. Например, скажем, у вас есть базовый двигатель, и вы хотите сделать новый двигатель с наддувом. Что ж, 99% двигателя, который вы будете использовать, но вы немного настроите его функциональность, чтобы он запустил намного лучше, и все же существует некоторая функциональность, которая должна быть показана только в сделанных модификациях, а не конечным пользователю. Потому что все мы знаем, что каждый класс, который выпускает MS, на самом деле никогда не нуждаются в каких -либо изменениях.

Помимо использования нового, чтобы просто переопределить функциональность, это одна из вещей, которые Microsoft в их бесконечной WI ... ... о, я имею в виду ошибки, которые считаются инструментом, который больше не стоит.

Лучший способ сделать это сейчас-многоуровневое наследство.

public class classA 
{
}

public class B : A 
{} 

public class C : B 
{} 

Класс B выполняет всю вашу работу, а класс С раскрывает то, что вам нужно.

Вы не можете, это весь смысл наследования: подкласс должен предлагать все методы и свойства базового класса.

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

Я думаю, что это плохой дизайн, если вам нужно это сделать, особенно если вы можете разработать код с нуля.

Почему?

Хороший дизайн-позволить базовому классу разделять общие свойства, которые имеет определенная концепция (виртуальная или реальная). Пример: System.io.stream в C#.

Далее вниз по переулке Bad Design увеличит стоимость технического обслуживания и усложнит реализацию. Избегайте этого как можно больше!

Основные правила, которые я использую:

  • Минимизировать количество свойств и методов в базовом классе. Если вы не ожидаете использовать некоторые свойства или методы в классе, который наследует базовый класс; Не кладите это в Baseclass тогда. Если вы находитесь на разработке проекта; Всегда возвращайтесь к доски на рисунках, а затем проверить дизайн, потому что все меняется! Редизайна при необходимости. Когда ваш проект будет жить, затраты на изменение вещи позже в дизайне растут!

    • Если вы используете BaseClass, реализованное стороной 3: RD, рассмотрите возможность «перейти» на один уровень вместо «переоценки» с «notimplementedException» или тому подобным. Если нет другого уровня, рассмотрите возможность разработки кода с нуля.

    • Всегда рассмотрите возможность запечатать классы, которые вы не хотите, чтобы кто -то мог унаследовать его. Это заставляет кодеров «подниматься на один уровень» в «наследстве- иерархии» и, следовательно, можно избежать «свободных концов», подобных «notimplementedException».

I know that the question is old, but what you can do is override the PostFilterProperties like this:

 protected override void PostFilterProperties(System.Collections.IDictionary properties)
    {
        properties.Remove("AccessibleDescription");
        properties.Remove("AccessibleName");
        properties.Remove("AccessibleRole");
        properties.Remove("BackgroundImage");
        properties.Remove("BackgroundImageLayout");
        properties.Remove("BorderStyle");
        properties.Remove("Cursor");
        properties.Remove("RightToLeft");
        properties.Remove("UseWaitCursor");
        properties.Remove("AllowDrop");
        properties.Remove("AutoValidate");
        properties.Remove("ContextMenuStrip");
        properties.Remove("Enabled");
        properties.Remove("ImeMode");
        //properties.Remove("TabIndex"); // Don't remove this one or the designer will break
        properties.Remove("TabStop");
        //properties.Remove("Visible");
        properties.Remove("ApplicationSettings");
        properties.Remove("DataBindings");
        properties.Remove("Tag");
        properties.Remove("GenerateMember");
        properties.Remove("Locked");
        //properties.Remove("Modifiers");
        properties.Remove("CausesValidation");
        properties.Remove("Anchor");
        properties.Remove("AutoSize");
        properties.Remove("AutoSizeMode");
        //properties.Remove("Location");
        properties.Remove("Dock");
        properties.Remove("Margin");
        properties.Remove("MaximumSize");
        properties.Remove("MinimumSize");
        properties.Remove("Padding");
        //properties.Remove("Size");
        properties.Remove("DockPadding");
        properties.Remove("AutoScrollMargin");
        properties.Remove("AutoScrollMinSize");
        properties.Remove("AutoScroll");
        properties.Remove("ForeColor");
        //properties.Remove("BackColor");
        properties.Remove("Text");
        //properties.Remove("Font");
    }

You can use Browsable(false)

[Browsable( false )]
public override string Name
{
    get { return base.Name; }
    set { base.Name= value; }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top