Как скрыть метод, чтобы он не вызывался программистами, а мог использоваться в коде? - PullRequest
4 голосов
/ 07 ноября 2008

У меня есть класс с именем Ship и класс с именем Lifeboat

Спасательная шлюпка наследуется от Корабля.

Ship содержит метод с именем Validate(), который вызывается перед сохранением, и имеет абстрактный метод с именем FurtherValidate(), который вызывается из Validate. Причина этого в том, что когда вы вызываете validate на базе, он также проверяет класс, который наследует. Итак, у нас есть

public class Ship

public bool Validate()
{
    //validate properties only found on a ship

    FurtherValidate();
}

public abstract bool FurtherValidate();

То есть Lifeboat имеет

public override bool FurtherValidate()
{
    //validate properties only found on a lifeboat
}

Это означает, что любой, внедряющий Ship, также должен предоставить свою собственную проверку для своего класса, и он гарантированно будет вызван на сохранение как базовый корабль. Вызывается Validate(), который в свою очередь вызывает унаследованную проверку.

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

Ответы [ 9 ]

7 голосов
/ 07 ноября 2008

Короткий ответ: вы не можете скрыть производный метод от класса, который его выводит. Тем не менее, вы можете реорганизовать свой код для достижения того, чего вы пытаетесь достичь:

public class Ship
{    
    public virtual bool Validate()    
    {        
        //validate properties only found on a ship
        return true;
    }
}
public class Lifeboat : Ship
{   
    public override bool Validate()   
    {       
        base.Validate();       
        // lifeboat specific code
        return true;
    }
}
7 голосов
/ 07 ноября 2008
protected abstract bool FurtherValidate();

Только корабль и спасательная шлюпка могут видеть это сейчас.

EDIT: Спасательная шлюпка должна видеть это. Как он должен иметь возможность переопределить FurtherValidate, когда он даже не видит его. Я бы переименовал его в ValidateCore, часть «Ядра» (для меня) подразумевает, что его нельзя вызывать без веской причины.

Я не думаю, что это легко сделать абстрактным, но не видимым. Вы должны верить в свою спасательную шлюпку;)

4 голосов
/ 07 ноября 2008

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

Использование атрибута [EditorBrowsable] - это трюк IDE, который скрывает метод от IntelliSense (если только другой программист не включил правильные параметры в VS). Это будет эффективно препятствовать тому, чтобы большинство людей назвало это (если они не могут видеть это, это не существует).

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

3 голосов
/ 07 ноября 2008

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

Я был бы более склонен полностью удалить метод AdditionalValidate, и любые наследуемые классы переопределяют Validate, вызывая base.Validate (), если они захотят. Это позволяет любому классу, который наследуется от корабля, иметь большую степень контроля над методом validate.

2 голосов
/ 07 ноября 2008

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

1 голос
/ 07 ноября 2008

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

protected IValidator FurtherValidation { private get; set; }

public bool Validate()
{
//validate properties only found on a ship

    if (FurtherValidation == null)
        throw new ValidationIsRequiredException();
    if (!FurtherValidation.IsValid(this))
        // logic for invalid state
}
1 голос
/ 07 ноября 2008

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

0 голосов
/ 07 ноября 2008

Возможно, вы могли бы попробовать частный модификатор

0 голосов
/ 07 ноября 2008

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

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