C# - Могут публично наследованные методы быть скрытыми (например, сделанными частные к производному классу)

Я новичок в SQL, но столкнулся с этой проблемой в ходе курса, который я принимал, и обнаружил, что назначение запроса проекту специально помогло устранить многочастную ошибку. Например, проект, который я создал, был CTU SQL Project, поэтому я убедился, что начал свой сценарий с USE [CTU SQL Project] в качестве первой строки, как показано ниже.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
56
задан Don Kirkby 30 November 2008 в 05:56
поделиться

9 ответов

Это не возможно, почему?

В C#, это вызывается на Вас, что при наследовании открытых методов необходимо обнародовать их. Иначе они ожидают, что Вы не произойдете из класса во-первых.

Вместо того, чтобы использовать - отношения, необходимо было бы использовать - отношения.

разработчики языка не позволяют это нарочно так, чтобы Вы использовали наследование более правильно.

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

, Таким образом, они не позволяют ему защищать Вас от плохих иерархий наследования.

, Что необходимо сделать вместо этого?

Вместо этого необходимо реализовать интерфейсы. Это оставляет Вас свободными иметь функциональность с помощью - отношения.

Другие языки:

В C++ Вы просто определяете модификатор перед базовым классом частных, общедоступных или защищенных. Это делает всех членов основы, которые были общедоступны к тому указанному уровню доступа. Кажется глупым мне, что Вы не можете сделать того же в C#.

реструктурированный код:

interface I
{
    void C();
}

class BaseClass
{
    public void A() { MessageBox.Show("A"); }
    public void B() { MessageBox.Show("B"); }
}

class Derived : I
{
    public void C()
    {
        b.A();
        b.B();
    }

    private BaseClass b;
}

я понимаю, что названия вышеупомянутых классов немного спорны:)

Другие предложения:

Другие предложили сделать () и B () общественность и выдать исключения. Но это не делает дружественный класс для людей для использования, и он действительно не имеет смысла.

70
ответ дан Daniel Daranas 7 November 2019 в 16:37
поделиться

Это походит на плохую идею. Liskov не был бы впечатлен.

, Если Вы не хотите, чтобы потребители DerivedClass были в состоянии к методам доступа DeriveClass. () и DerivedClass. B () я предложил бы, чтобы DerivedClass реализовал некоторый открытый интерфейс, IWhateverMethodCIsAbout и потребители DerivedClass должны на самом деле говорить с IWhateverMethodCIsAbout и ничего не знать о реализации BaseClass или DerivedClass вообще.

6
ответ дан Hamish Smith 7 November 2019 в 16:37
поделиться

то, В чем Вы нуждаетесь, является составом не наследование.

class Plane
{
  public Fly() { .. }
  public string GetPilot() {...}
}

Теперь при необходимости в специальном виде Плоскости, такой как та, которая имеет PairOfWings = 2, но иначе делает все, плоскость может.. Вы наследовали плоскость. Этим Вы объявляете, что Ваша деривация выполняет контракт базового класса и может быть заменена, не мигая везде, где базовый класс ожидается. например, LogFlight (Плоскость) продолжил бы работать с экземпляром BiPlane.

Однако, если Вам просто нужно поведение Мухи для нового Bird, Вы хотите создать и не готовы поддерживать полный контракт базового класса, Вы сочиняете вместо этого. В этом случае осуществите рефакторинг поведение методов к повторному использованию в новый Полет типа. Теперь создайте и держите ссылки на этот класс и в Плоскости и в Bird. Вы не наследовались, потому что Bird не поддерживает полный контракт базового класса... (например, он не может обеспечить GetPilot ()).

По той же причине, Вы не можете уменьшить видимость методов базового класса, когда Вы переопределяете.. можно переопределить и обнародовать основной закрытый метод в деривации, но не наоборот. например, В этом примере, если я получаю тип Плоскости "BadPlane" и затем переопределяю и "Скрываю" GetPilot () - делают его частным; клиентский метод LogFlight (Плоскость p) будет работать на большинство Плоскостей, но аварийно завершится для "BadPlane", если реализация LogFlight, окажется, будет нуждаться/называть в GetPilot (). , Так как все деривации базового класса, как ожидают, будут 'substitutable' везде, где параметрический усилитель базового класса ожидается, это должно быть запрещено.

5
ответ дан Gishu 7 November 2019 в 16:37
поделиться

Единственный способ сделать это, что я знаю о, должно использовать - отношения и только реализовать функции, которые Вы хотите представить.

3
ответ дан Nescio 7 November 2019 в 16:37
поделиться

@Brian R. Bondy указал на меня на интересную статью о Сокрытии посредством наследования и новый ключевое слово.

http://msdn.microsoft.com/en-us/library/aa691135 (По сравнению с 71) .aspx

Поэтому как обходное решение я предложил бы:

class BaseClass
{
    public void A()
    {
        Console.WriteLine("BaseClass.A");
    }

    public void B()
    {
        Console.WriteLine("BaseClass.B");
    }
}

class DerivedClass : BaseClass
{
    new public void A()
    {
        throw new NotSupportedException();
    }

    new public void B()
    {
        throw new NotSupportedException();
    }

    public void C()
    {
        base.A();
        base.B();
    }
}

Этот путь код как это бросит NotSupportedException:

    DerivedClass d = new DerivedClass();
    d.A();
3
ответ дан Michael Myers 7 November 2019 в 16:37
поделиться

Сокрытие является довольно скользким путем. Основные вопросы, IMO:

  • Это зависит от типа объявления времени проектирования экземпляра, означая, делаете ли Вы что-то как BaseClass obj = новый SubClass (), затем назовите obj. (), сокрытие побеждено. BaseClass. () будет выполняться.

  • Сокрытие может очень легко затенить поведение (или изменения поведения) в базовом типе. Это - очевидно, меньше беспокойства при владении обеими сторонами уравнения, или если вызов 'base.xxx' является частью подучастника.

  • , Если Вы на самом деле делаете собственный обе стороны уравнения основы/подкласса, тогда необходимо быть в состоянии создать более управляемое решение, чем узаконенное сокрытие/затенение.
1
ответ дан Jared 7 November 2019 в 16:37
поделиться

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

предстоящую парадигму кодирования называют "Составом по Наследованию". Это играет непосредственно прочь принципов объектно-ориентированной разработки (особенно Единственный Принцип Ответственности, и Откройтесь/Закройте Principle).

, К сожалению, путь многие из нас разработчикам преподавали объектную ориентацию, мы сформировали привычку к непосредственному размышлению о наследовании вместо состава. Мы склонны иметь большие классы, которые имеют много различных обязанностей просто, потому что они могли бы содержаться с тем же объектом "Реального мира". Это может привести к иерархиям классов, которые равняются 5 + уровни глубоко.

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

Один способ разбить Ваш код через интерфейсы, любят упомянутый в другом ответе. Это - умная вещь сделать так или иначе, поскольку Вы хотите, чтобы внешние зависимости класса связали с абстракциями, не бетоном/производными типами. Это позволяет Вам изменять реализацию, не изменяя интерфейс, все, не производя строку кода в Вашем зависимом классе.

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

, Возможно, лучший ресурс там на объектно-ориентированной разработке является книгой Robert C. Martin, Гибкая разработка программного обеспечения, Принципы, Шаблоны и Методы .

1
ответ дан Jason Olson 7 November 2019 в 16:37
поделиться

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

Редактирование: Jorge Ferreira корректен.

0
ответ дан Cody Brocious 7 November 2019 в 16:37
поделиться

Когда вы, например, пытаетесь наследовать от List , и хотите скрыть прямой член Add (object _ob) :

// the only way to hide
[Obsolete("This is not supported in this class.", true)]
public new void Add(object _ob)
{
    throw NotImplementedException("Don't use!!");
}

Это не действительно наиболее предпочтительное решение, но оно делает свою работу. Intellisense по-прежнему принимает, но во время компиляции вы получаете сообщение об ошибке:

ошибка CS0619: «TestConsole.TestClass.Add (TestConsole.TestObject)» устарело: «Это не поддерживается в этом классе»

28
ответ дан 26 November 2019 в 17:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: