Вопрос по constructor, c#, abstract-class, oop, inheritance – Вызывать переопределения в конструкторе не рекомендуется.

57

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

public abstract class A
{
    abstract A(int a, int b);
}

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

public class B : A
{
    public B(int a, int b) : base(a, b)
    {
        //Some other awesome code.
    }
}

Это весь код C # .NET. Может кто-нибудь мне помочь?

Обновление 1

Я хотел добавить некоторые вещи. То, что я закончил, было этим.

private A() { }

protected A(int a, int b)
{
    //Code
}

Это делает то, что говорят некоторые люди, по умолчанию это private, и класс должен реализовывать конструктор. Однако это не заставляет конструктор с подписью A (int a, int b).

public abstract class A
{
    protected abstract A(int a, int b)
    {


    }
}

Обновление 2

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

Сегодня миры POO не понимают концепции переопределения общего ресурса (конструкторы являются общими методами, событие, если .net означает, что он не является общим, в действительности это общий метод, потому что вы можете вызывать его везде, и ему не нужен экземпляр). Так что переопределение общего доступа Это странная особенность, которую понимают немногие языки (например, Haskell). Toto
Это была опечатка, (должен был быть int b), но мой ответ был очень похож на Джейми, поэтому я удалил свой. BFree

Ваш Ответ

8   ответов
26

Измените этот конструктор в классе A на

protected A(int a, int b)
{
    // Some initialisation code here
}

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

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

Для чего именно это нужно? Мы могли бы предложить обойти это.

Меняет ли C # 6 это правило с первичными конструкторами? Ray Koopa
Тем не менее это правильно. Отрегулируйте, что вы хотите к реальности;) TomTom
Этот ответ не выполняет то, что я хочу. Anthony D
Я думаю, что они могут добавить другие конструкторы (с другой сигнатурой), но они будут вынуждены реализовать хотя бы сигнатуру, как определено в защищенном «конструкторе». Thorsten
1

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

я не знал этого раньше: если вы делаете защищенный ctor, то дочерний класс видит его, но остальная часть программы не видит его (я предполагаю, что моя путаница заключается в том, что в asp.net я вижу все защищенные на странице aspx, которая наследуется от CS ...)

спасибо за информацию: D bresleveloper
На самом деле .aspx и .aspx.cs оба определяют один и тот же класс. Таким образом, страница .aspx не «наследует» класс в коде .aspx.cs (несмотря на то, что она упоминается в<%Page%> директива как «Наследует»), но на самом деле определяет частичное к тому же классу. CptRobby
4

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

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

0

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

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

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

«Вот как это работает в Java» - но он не спрашивает о Java ... Aran Mulholland
6

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

public abstract class A 
{ 
    abstract A MakeAInstance(int a, int b); 
} 

public class B : A 
{ 
    // Must implement:
    override A MakeAInstance(int a, int b) {
        // Awesome way to create a B instance goes here
    }
} 
Да, точно, или нужно передать в ваш код, который затем вызываетinstance.MakeAInstance(1,2) John Saunders
но в этом случае вы должны сначала создать экземпляр класса B, чтобы иметь возможность вызвать метод MakeAInstance и получить новый DkAngelito
49

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

Если задуматься, это имеет смысл, поскольку вы всегда вызываете конструктор дочернего класса (с оператором new), а не базовый класс.

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

Можете ли вы привести пример сnew()? Разве это не опасное ключевое слово, которое скрывает унаследованный член, или это что-то еще? JeromeJ
5

1) Конструкторы не наследуются, поэтому вы не можете их переопределить.

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

Конструктор является методом экземпляра (то есть нестатическим методом), как видно из перспективы CIL. Это может выглядеть так:.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ... } Так его зовут.ctor, этоinstance неstaticи его тип возвратаvoid, (Его доступность может отличаться отpublicи его список параметров может содержать некоторые аргументы.) Jeppe Stig Nielsen
Я не согласен с вашим утверждением о том, что конструктор является статическим членом, ему нужен экземпляр для вызова (поскольку вы можете обращаться к методам экземпляра, полям и т. Д.).new Ключевое слово создает объект, а затем вызывается конструктор, сам конструктор не "конструирует" объект. Matthew
0

поможет ли это - но я чувствую, что это решение вашей проблемы:

public class A
{
  public A(int a, int b)
  {
    DoSomething(int a, int b);
  }

  virtual public void DoSomething(int a, int b)
  {

  }
}

public class B : A
{
  override public void DoSomething(int a, int b)
  {
    //class specific stuff
  }
}

в результате вы можете вызвать конструктор с необходимыми аргументами в любом производном классе с правильным поведением.

Вызывать переопределения в конструкторе не рекомендуется. Tilak

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