Понимание Наследования - PullRequest
2 голосов
/ 31 мая 2010

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

Например, на днях я думал о связи Непогрешимого Человека и Ошибочного Человека. Давайте сначала определим два:

  • Непогрешимый человек: Человек, который никогда не совершит ошибку. Его метод do_task () никогда не вызовет исключение
  • Человек с ошибками: Человек, который иногда совершает ошибки. Его метод do_task () может иногда выдавать исключение ErrorProcessingRequest

Вопрос был: Является ли непогрешимый человек Ошибочным человеком ИЛИ Является ли ошибочный человек НАД непогрешимым человеком?

Очень хороший ответ, который я получил, был в форме вопроса (я люблю их, так как он дает мне правила для ответов на будущие вопросы, которые у меня могут быть).

"Можете ли вы пройти безошибочного человека там, где ожидается ошибочный человек ИЛИ вы можете пройти безошибочного человека там, где ожидается безошибочный человек?"

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

Тем не менее, это все еще забавно говорить "непогрешимый человек - ошибочный человек". Кто-нибудь еще чувствует тошноту, когда говорит это? Кажется, будто произнесение деревьев наследования подобно чтению высказываний из исчисления высказываний на простом английском языке (соединительные выражения «если / тогда» не означают то же, что и в разговорном английском). Кто-нибудь еще чувствует то же самое?

Ответы [ 5 ]

8 голосов
/ 31 мая 2010

"Кажется очевидным, что вы можете пройти непогрешимый человек, где ошибаться человек ожидается, но не другой наоборот "

Это только правильное предположение в определенном контексте. Разбейте это так:

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

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

Другими словами, полностью зависит от требований системы определить ответ на вопрос "IS an infallible human A fallible human OR IS a fallible human AN infallible human?".

Тот факт, что логические объекты были антропоморфизированы, вероятно, более запутанен, чем что-либо еще, потому что кажется, что ваше заблуждение проистекает из философской точки зрения, а не из логической. Замените «непогрешимый человек» и «ошибочный человек» на «объект X» и «объект Y», и это может прояснить для вас мышление.

5 голосов
/ 31 мая 2010

В этом случае я бы сказал, что родительский класс является ответом: FallibleHuman наследует от Human, как и InFallibleHuman.

2 голосов
/ 31 мая 2010

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

Что общего у людей? У всех людей есть открытый метод do_task () и закрытый / защищенный метод do_something (). Итак, мы описываем, что это супер класс под названием "Человек"

public abstract class Human
{
    // describes commonality
    public abstract void do_task();

    // provides common functionality
    protected virtual void do_something()
    {
        throw new Exception("I made a mistake");
    }
}

и теперь «унаследованные» классы реализуют свою собственную специфическую логику для метода do_task (), но у них есть общая функциональность защищенного метода do_something ()

public class InfallibleHuman : Human
{
    public override void do_task()
    {
        try
        {
            do_something();
        }
        catch
        {
            // never throw an exception
            // because I never make mistakes
        }
    }   
}

public class FallibleHuman : Human
{
    public override void do_task()
    {
        do_something();
        // always throw an exception if
        // something goes wrong because I'm accountable
        // for my own actions
    }
}

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

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

public void ImPrettyTolerantOfMistakes()
{
    try
    {
        Human anyHumanWillDo = new FallibleHuman();
        anyHumanWillDo.do_task();
        Human anotherHuman = new InfallibleHuman();
        anotherHuman.do_task();
    }
    catch
    {
        // I'll take care of a human
        // making a mistake
    }
}

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

public void ImIntolerantOfHumansWhoMakeMistakes()
{
    InfallibleHuman onlyAPerfectHumanWillDo = new InfallibleHuman();
    onlyAPerfectHumanWillDo.do_task();

    // if this guy fails, I'm dead meat
}

Надеюсь, все немного прояснится для вас.

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

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

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

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

Я согласен с Daenyth ...

Поскольку один раз никогда не может ошибаться, а кто-то делает, логически это ответ.

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

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

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