Абстрактный класс использует свой собственный абстрактный метод? - PullRequest
3 голосов
/ 04 октября 2011

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

public abstract class Entity
{

    public Entity(World world)
    {
        // irrelevent code
        entityInit();
    }

    protected abstract void entityInit();
}

Что здесь происходит? Что происходит, когда он вызывает entityInit()?

Ответы [ 7 ]

7 голосов
/ 04 октября 2011

Абстрактный класс никогда не создается.Только его конкретные подклассы могут быть созданы.Итак, когда вызывается конкретный конструктор подкласса (назовем его Foo), он вызывает super(world).Затем конструктор Entity вызывает entityInit(), который был переопределен на Foo.Таким образом, он вызывает конкретный метод Foo entityInit.

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

3 голосов
/ 04 октября 2011

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

Вызов абстрактных методов из кода класса abstact на самом деле совершенно обычен, и в этом весь смысл абстрактных методов. Смотрите также шаблон метода шаблона .

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

2 голосов
/ 04 октября 2011

Ну, в основном, это используется в шаблонном шаблоне . Не подвластный классу подкласс Entity будет реализовывать метод entityInit(). Эти подклассы реализуют способ, которым их entityInit() должны быть определены для этого класса.

В Википедии написано ....

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

В вашем случае вам не нужно беспокоиться о том, что подклассы сами должны entityInit(), поскольку конструктор сделает это по умолчанию:

Пример:

public class StrictEntity extends Entity {

    public StrictEntity(World world) {
        super(world); //This will call entityInit();
    }

    protected void entityInit() {
        //Example, don't take it as genuine.
        PropertyConfig.getInstance.setStrict(true);
    }
}
1 голос
/ 04 октября 2011

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

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

Одно замечание: учтите, что при доступе к полям, определенным в подклассе, доступ к ним в entityInit() может привести к исключению NullPointerException, поскольку они могут не инициализироваться.Пример (на основе вашего класса):

class Person extens Entity {
   private String name = "Player";

   protected void entityInit() {
     int nameLen = name.length(); //NPE here!!!
   }
}

Хотя этот пример не имеет большого логического смысла, он должен проиллюстрировать это.Сначала будет вызван конструктор Entity, который, в свою очередь, вызовет entityInit().Однако, поскольку блок инициализатора Person еще не запущен, name по-прежнему равен нулю.

1 голос
/ 04 октября 2011

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

1 голос
/ 04 октября 2011

Ну, ничего.

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

0 голосов
/ 04 октября 2011

Не вызывайте абстрактные / виртуальные методы из конструктора.это вызвало бы конкретную реализацию подкласса.Но переменные-члены конкретного подкласса не инициализировались бы.

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

Но в этом конкретном случае вся цельметода заключается в инициализации членов объекта this.Так что все в порядке.но при таком подходе мы должны связать вызов метода суперкласса (если он имеет реализацию).

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