избегая, если заявления - PullRequest
       56

избегая, если заявления

36 голосов
/ 27 августа 2009

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

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

EDIT

Ничего себе, это не заняло много времени. Я полагаю, это слишком экстремально. Можно ли сказать, что при ООП вы должны ожидать гораздо меньше заявлений?

ВТОРОЕ РЕДАКТИРОВАНИЕ

Как насчет этого: объект, который определяет реализацию своего метода на основе своих атрибутов. То есть вы можете реализовать someMethod() двумя способами и указать некоторые ограничения. В любой момент объект будет направлен к правильной реализации метода на основе его свойств. Так что в случае if(x > 5) просто есть два метода, которые опираются на атрибут x

Ответы [ 24 ]

3 голосов
/ 27 августа 2009

В ответ на вопрос ifTrue:

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

class Nat {
    def cond = {
        print this;
        return this;
    }
}

class NatLessThan<5:Nat> { // subclass of Nat
    override cond = {
        return 0;
    }
}

x = x.cond();

(продолжение ...)

Или без открытых классов, но с несколькими диспетчерскими и анонимными классами:

class MyCondFunctor {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}

x = new MyCondFunctor.branch(x);

Или, как и раньше, но с анонимными классами:

x = new {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}.branch(x);

Вам бы, конечно, было бы намного легче, если бы вы изменили эту логику. Помните, что существуют полностью тьюрингово-полные системы типов.

2 голосов
/ 27 августа 2009

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

2 голосов
/ 28 июля 2017
Assume we have conditional values.

public void testMe(int i){

if(i=1){
somevalue=value1;
}


if(i=2){
 somevalue=value2;
}

if(i=3){
somevalue=value3;
}

}

//**$$$$$you can replace the boring IF blocks with Map.$$$$$**

// ============================================= ===============

Same method would look like this:
--------------------------------
public void testMe(int i){

Map<Integer,String> map = new HashMap<Integer,String>();

map.put(1,value1);
map.put(2,value2);
map.put(3,value3);

}
This will avoid the complicated if conditions.

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

public void loadAnimalsKingdom(String animalKingdomType)
    if(animalKingdomType="bird"){
    Bird b = new Bird();
    }
    if(animalKingdomType="animal"){
    Animal a= new Animal();
    }
    if(animalKingdomType="reptile"){
    Reptile r= new Reptile();
    }
  }

Теперь используя карту:

   public void loadAnimalsKingdom(String animalKingdomType)
    {
       Map <String,String> map = new HashMap<String,String>();

       map.put("bird","com.animalworld.Bird.Class");
       map.put("animal","com.animalworld.Animal.Class");
       map.put("reptile","com.animalworld.Reptile.Class");

       map.get(animalKingdomType);

***Use class loader to load the classes on demand once you extract the required class from the map.***
}

Понравилось решение? Дай палец вверх. - Vv

1 голос
/ 27 августа 2009

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

1 голос
/ 27 августа 2009

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

0 голосов
/ 27 августа 2009

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

Вот пример реализации Python, которую я писал в прошлом для deque фиксированного размера (двусторонняя очередь). Вместо того чтобы создавать метод «remove» и иметь внутри него операторы if, чтобы увидеть, является ли список полным или нет, вы просто создаете два метода и переназначаете их для функции «remove» по мере необходимости.

В следующем примере перечислен только метод «удалить», но, очевидно, существуют методы «добавления» и тому подобное.

class StaticDeque(collections.deque):

    def __init__(self, maxSize):

        collections.deque.__init__(self)
        self._maxSize = int(maxSize)
        self._setNotFull()

    def _setFull(self):

        self._full = True
        self.remove = self._full_remove

    def _setNotFull(self):

        self._full = False
        self.remove = self._not_full_remove

    def _not_full_remove(self,value):

        collections.deque.remove(self,value)

    def _full_remove(self,value):

        collections.deque.remove(self,value)
        if len(self) != self._maxSize and self._full:
            self._setNotFull()

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

0 голосов
/ 27 августа 2009

If-операторы - это ядро ​​программирования, поэтому, короче говоря, вы не можете их разумно избегать.

Однако ключевой целью в ООП - фактически, одним из «столпов» - является инкапсуляция. Старое правило «инкапсулировать то, что меняется» помогает вам удалить те проблемные операторы if и case, в которых вы пытаетесь учесть каждый параметр в вашем объекте. Лучшее решение для работы с ветками, особыми случаями и т. Д. - использовать что-то вроде шаблона проектирования «Фабрика» (Абстрактный Фабрика или Фабричный метод - конечно, в зависимости от потребностей).

Например, вместо того, чтобы ваш основной цикл кода проверял, с какой ОС вы используете операторы if, затем переходите к созданию окон GUI с различными параметрами для каждой ОС, ваш основной код будет создавать объект фабрики, которая использует ОС для определите, какой конкретный объект для конкретной ОС сделать. При этом вы извлекаете варианты (и длинные предложения if-then-else) из основного цикла кода и позволяете дочерним объектам обрабатывать его - так что в следующий раз вам нужно будет внести изменения, такие как поддержка новой ОС вы просто добавляете новый класс из интерфейса фабрики.

0 голосов
/ 27 августа 2009

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

Операторы if, безусловно, имеют свое место в объектно-ориентированном дизайне.

0 голосов
/ 26 сентября 2009

Мои два бита о том, что я понимаю в отношении объектно-ориентированного подхода -

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

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

Объектно-ориентированный подход, на мой взгляд, не является заменой процедурного подхода. Скорее это главным образом по двум основным причинам для создателей языка -

  1. Лучшая возможность определения переменных.

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

0 голосов
/ 27 августа 2009

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

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

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