Почему я не могу создать абстрактный конструктор в абстрактном классе C #? - PullRequest
58 голосов
/ 03 февраля 2009

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

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 # не позволяет вам сделать это.

Ответы [ 8 ]

50 голосов
/ 03 февраля 2009

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

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

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

26 голосов
/ 03 февраля 2009

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

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

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

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

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

6 голосов
/ 05 мая 2010

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

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
    }
} 
5 голосов
/ 29 марта 2012

Несколько причин:

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

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

4 голосов
/ 03 февраля 2009

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

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

1 голос
/ 10 июля 2012

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

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

0 голосов
/ 05 мая 2010

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

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

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

0 голосов
/ 03 февраля 2009

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

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

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

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