Как осуществить вызов метода (в базовом классе), когда метод переопределения вызывается?

Теория (для адвокатов языка и математически наклоненный):

equals() ( javadoc) должен определить отношение эквивалентности (это должно быть рефлексивно , симметричный , и переходный ). Кроме того, это должно быть последовательно (если объекты не изменяются, то это должно продолжать возвращать то же значение). Кроме того, o.equals(null) должен всегда возвращать false.

hashCode() ( javadoc) должен также быть последовательны (если объект не изменяется с точки зрения equals(), это должно продолжать возвращать то же значение).

отношение между этими двумя методами:

Каждый раз, когда a.equals(b), тогда a.hashCode() должно быть то же как b.hashCode().

На практике:

, Если Вы переопределяете один, тогда необходимо переопределить другой.

Использование тот же набор полей, которые Вы используете для вычисления equals() для вычисления hashCode().

Использование превосходные классы помощника EqualsBuilder и HashCodeBuilder от библиотека Commons Lang Apache. Пример:

public class Person {
    private String name;
    private int age;
    // ...

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
            // if deriving: appendSuper(super.hashCode()).
            append(name).
            append(age).
            toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
       if (!(obj instanceof Person))
            return false;
        if (obj == this)
            return true;

        Person rhs = (Person) obj;
        return new EqualsBuilder().
            // if deriving: appendSuper(super.equals(obj)).
            append(name, rhs.name).
            append(age, rhs.age).
            isEquals();
    }
}

Также помните:

При использовании основанного на хеше Набор или Карта такой как [1 117] HashSet, LinkedHashSet, HashMap, Хеш-таблица , или WeakHashMap, удостоверяется, что хэш-код () ключевых объектов, которые Вы помещаете в набор, никогда не изменяется, в то время как объект находится в наборе. Пуленепробиваемый способ гарантировать это состоит в том, чтобы сделать Ваши ключи неизменными, , который обладает также другими преимуществами .

7
задан Coral Doe 28 June 2012 в 15:58
поделиться

4 ответа

Можно было бы, чтобы класс Abstract выполнял вызов таким образом. В противном случае в C # нет способа потребовать, чтобы унаследованный класс реализовал метод определенным образом.

public abstract class AbstractClass
{
    public void PerformThisFunction()
    {
        MustBeCalled();
        AbstractMethod();
    }

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }

    //could also be public if desired
    protected abstract void AbstractMethod();
}

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

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

8
ответ дан 6 December 2019 в 19:40
поделиться

How about

public abstract class AbstractClass
{
    public void AbstractMethod()
    {
        MustBeCalled();
        InternalAbstractMethod();
    }

    protected abstract void InternalAbstractMethod();

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }
}

public class ImplementClass : AbstractClass
{
    protected override void InternalAbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}
6
ответ дан 6 December 2019 в 19:40
поделиться

Одна вещь, которую игнорируют предыдущие решения, это то, что ImplementClass может переопределять MethodToBeCalled и не вызывать MustBeCalled -

public abstract class AbstractClass
{
    public abstract void AbstractMethod();

    private void MustBeCalled()
    {
        //will be invoked by  MethodToBeCalled();
        Console.WriteLine("AbstractClass.MustBeCalled");
    }

    public void MethodToBeCalled()
    {
        MustBeCalled();
        AbstractMethod();
    }
}

public class ImplementClass : AbstractClass
{
    public override void AbstractMethod()
    {
        Console.WriteLine("ImplementClass.InternalAbstractMethod");
    }

    public new void MethodToBeCalled() {
        AbstractMethod();
    }
}

Если только C # позволяет запечатывать непереопределенные методы - например, ключевое слово final в Java!

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

namespace Something
{

    public sealed class OuterClass
    {
        private AbstractInnerClass inner;

        public OuterClass(AbstractInnerClass inner)
        {
            this.inner = inner;
        }

        public void MethodToBeCalled()
        {
            MustBeCalled();
            inner.CalledByOuter();
        }

        public void MustBeCalled()
        {
            //this must be called when AbstractMethod is invoked
            System.Console.WriteLine("OuterClass.MustBeCalled");
        }
    }

    public abstract class AbstractInnerClass
    {
        internal void CalledByOuter()
        {
            AbstractMethod();
        }

        protected abstract void AbstractMethod();
    }
}

public class ImplementInnerClass : Something.AbstractInnerClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
        System.Console.WriteLine("ImplementInnerClass.AbstractMethod");
    }

    public new void CalledByOuter()
    {
        System.Console.WriteLine("doesn't work");
    }
}
0
ответ дан 6 December 2019 в 19:40
поделиться

Why can't you just call the method in the AbstractMethod() of Implement class?

-1
ответ дан 6 December 2019 в 19:40
поделиться
Другие вопросы по тегам:

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