Подтвердить что ты не робот

Вызов метода базовой базы

Есть ли конструкция в Java или С#, которая заставляет наследовать классы для вызова базовой реализации? Вы можете вызвать super() или base(), но возможно ли, чтобы он выдавал ошибку времени компиляции, если она не вызвана? Это было бы очень удобно..

- редактировать -

Мне в основном интересуются переопределяющие методы.

4b9b3361

Ответ 1

Нет и не должно быть ничего такого.

Ближайшая вещь, которую я могу придумать, если что-то вроде этого в базовом классе:

public virtual void BeforeFoo(){}

public void Foo()
{

this.BeforeFoo();
//do some stuff
this.AfterFoo();

}

public virtual void AfterFoo(){}

И разрешить класс наследования переопределить BeforeFoo и/или AfterFoo

Ответ 2

Не в Java. Это возможно в С#, но кому-то придется поговорить с этим.

Если я правильно понял, вы хотите:

class A {
    public void foo() {
        // Do superclass stuff
    }
}

class B extends A {
    public void foo() {
        super.foo();
        // Do subclass stuff
    }
}

Что вы можете сделать в Java для обеспечения использования суперкласса foo, это что-то вроде:

class A {
    public final void foo() {
        // Do stuff
        ...
        // Then delegate to subclass
        fooImpl();
    }

    protected abstract void fooImpl();
}

class B extends A {
    protected void fooImpl() {
        // Do subclass stuff
    }
}

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

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

EDIT: Возможно, я неправильно понял вопрос. Вы говорите только о конструкторах или методах вообще? Я принимал методы вообще.

Ответ 3

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

Ответ 5

Нет. Это невозможно. Если у вас должна быть функция, которая выполняет некоторые операции до или после действия, выполните следующие действия:

internal class Class1
{
   internal virtual void SomeFunc()
   {
      // no guarantee this code will run
   }


   internal void MakeSureICanDoSomething()
   {
      // do pre stuff I have to do

      ThisCodeMayNotRun();

      // do post stuff I have to do
   }

   internal virtual void ThisCodeMayNotRun()
   {
      // this code may or may not run depending on 
      // the derived class
   }
}

Ответ 6

Я не читал ВСЕ ответы здесь; однако я рассматривал тот же вопрос. После просмотра того, что я ДЕЙСТВИТЕЛЬНО хотел сделать, мне показалось, что если я хочу, чтобы FORCE вызывал базовый метод, я не должен был сначала объявлять базовый метод виртуальным (переопределяемым).

Ответ 7

В следующем примере вызывается InvalidOperationException, когда базовая функциональность не наследуется при переопределении метода.

Это может быть полезно для сценариев, в которых метод вызывается некоторым внутренним API.

то есть. где Foo() не предназначен для прямого вызова:

public abstract class ExampleBase {
    private bool _baseInvoked;

    internal protected virtual void Foo() {
        _baseInvoked = true;
        // IMPORTANT: This must always be executed!
    }

    internal void InvokeFoo() {
        Foo();
        if (!_baseInvoked)
            throw new InvalidOperationException("Custom classes must invoke `base.Foo()` when method is overridden.");
    }
}

Работает:

public class ExampleA : ExampleBase {
    protected override void Foo() {
        base.Foo();
    }
}

Кричит:

public class ExampleB : ExampleBase {
    protected override void Foo() {
    }
}

Ответ 8

Не думайте, что есть встроенное решение. Я уверен, что есть отдельные инструменты анализа кода, которые могут это сделать.

Ответ 9

ИЗМЕНИТЬ Конструкция Misread в качестве конструктора. Оставляя как CW, так как он подходит к очень ограниченному подмножеству проблемы.

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

class Parent {
  protected Parent(int id) {
  }
}

class Child : Parent { 
  // Does not compile
  public Child() {}
  // Also does not compile
  public Child(int id) { }
  // Compiles
  public Child() :base(42) {}

}

Ответ 10

В java компилятор может применять только это в случае конструкторов.

Конструктор должен быть вызван по всей цепочке наследования. т.е. если Dog расширяет Animal extends Thing, конструктор для Dog должен вызвать конструктор для Animal, который должен вызвать конструктор для Thing.

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

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

public class Super
{
    public final void doIt()
    {
    // cannot be overridden
        doItSub();
    }

    protected void doItSub()
    {
     // override this
    }
}

public class Sub extends Super
{
    protected void doItSub()
    {
     // override logic
    }
}

Ответ 11

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

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

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

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

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

Я не проповедую это как Евангелие, и если люди видят недостаток этого подхода, я бы хотел услышать об этом.