Этот сайт щекотал мое чувство юмора - http://www.antiifcampaign.com/, но полиморфизм может работать в каждом случае, где Вы использовали бы если оператор?
Smalltalk, который считается "истинно" объектно-ориентированным языком, не имеет оператора "if", и не имеет оператора "for", оператора "while". Есть и другие примеры (например, Хаскелл), но это хороший пример.
Цитируя Smalltalk не имеет утверждения "if":
Некоторые зрители могут думать. что это доказательство, подтверждающее их подозрения, что Смоллток странный, но я собираюсь сказать тебе. это:
Утверждение "если" является мерзостью в языке, ориентированном на объект.
Почему? Ну, язык ОО состоит классов, объектов и методов, и заявление "если" не может быть неизбежным. из тех. Ты не можешь написать "если" на О, да. Его не должно существовать. Условное исполнение, как и все иначе, это должен быть метод. Метод Что? Булева.
А теперь, как ни странно, в Смоллтоке, У Булева есть метод, называемый ifTrue:ifFalse: (это имя будет выглядеть так. сейчас довольно странно, но передай это для того. Сейчас). В Булеве это абстракция, но... В Булеве есть два подкласса: Правда и Ложь. Метод проходит два блока кода. Правда, метод просто запускает код для истинного случая. На сайте Ложно, он запускает код для ложного... дело. Вот пример, который, будем надеяться. объясняет:
(x >= 0) ifTrue: [ "Положительный ] ifFalse: [ "Отрицательно ]
Вы должны увидеть, если это правда. если Ложь: там. Не волнуйся. они не вместе.
Выражение (x >= 0) оценивает, что правда или ложь. Скажи, что это правда, и тогда мы имеют:
истинное значение ifTrue: [ "Положительный ] ifFalse: [ "Отрицательно ]
Я надеюсь, что вполне очевидно, что что даст "Положительный".
Если бы это было ложно, мы бы имели:
ложный ifTrue: [ "Положительно ] ifFalse: [ "Отрицательно ]
Получается "Отрицательно".
Хорошо, вот как это делается. Что такое здорово в этом? Ну, в каком другом язык, ты можешь это сделать? Подробнее Серьёзно, ответ в том, что там в этом нет ничего особенного язык. Все может быть сделано в В стиле "OO", и все делается в OO путь.
Я определенно рекомендую прочитать весь пост и Код - это объект от того же автора.
На самом деле это игра в кодирование, в которую я люблю играть с языками программирования. Это называется «если бы у нас не было, если», и берет свое начало здесь: http://wiki.tcl.tk/4821
В основном, если мы запрещаем использование условных конструкций в языке: нет, если, нет while, no for, no if, no switch и т. д. можем ли мы воссоздать нашу собственную функцию IF. Ответ зависит от языка и от того, какие языковые возможности мы можем использовать (помните, что использование обычных условных конструкций обманывает троичные операторы!)
Например, в tcl имя функции - это просто строка и любая строка (включая пустую строка) разрешено для чего угодно (имена функций, имена переменных и т. д.). Итак, используя это, мы можем:
proc 0 {true false} {uplevel 1 $false; # execute false code block, ignore true}
proc 1 {true false} {uplevel 1 $true; # execute true code block, ignore flase}
proc _IF {boolean true false} {
$boolean $true $false
}
#usage:
_IF [expr {1<2}] {
puts "this is true"
} {
#else:
puts "this is false"
}
или в javascript мы можем злоупотребить свободной типизацией и тем фактом, что почти все может быть преобразовано в строку и сочетать это с ее функциональной природой:
function fail (discard,execute) {execute()}
function pass (execute,discard) {execute()}
var truth_table = {
'false' : fail,
'true' : pass
}
function _IF (expr) {
return truth_table[!!expr];
}
//usage:
_IF(3==2)(
function(){alert('this is true')},
//else
function(){alert('this is false')}
);
Не все языки могут делать такие вещи. Но языки, которые мне нравятся, как правило, умеют.
answer:**Сайт против использования выражений для **проверки, если объект имеет определенный тип. Это полностью отличается от if (foo == 5)
. Плохо использовать if как if (foo instanceof pickle)
. Альтернатива, использующая вместо этого полиморфизм, способствует инкапсуляции, делая код бесконечно простым для отладки, сопровождения и расширения.
Быть против , если
вообще (делать определенные вещи на основе условия) ничего не получится. Обратите внимание, что все остальные ответы здесь все еще принимают решения, так в чем же на самом деле разница?
Объяснение, почему за полиморхистом стоит:
Возьмем эту ситуацию:
void draw(Shape s) {
if (s instanceof Rectangle)
//treat s as rectangle
if (s instanceof Circle)
//treat s as circle
}
Намного лучше, если вам не придется беспокоиться об определенном типе объекта, обобщая, как объекты являются процессами.
void draw(Shape s) {
s.draw();
}
Это сдвигает логику того, как нарисовать фигуру в самом классе фигур, так что теперь мы можем одинаково относиться ко всем фигурам. Таким образом, если мы хотим добавить новый тип фигуры, все, что нам нужно сделать - это написать класс и дать ему метод отрисовки, вместо того, чтобы модифицировать каждый условный список во всей программе.
Эта идея сегодня повсюду в программировании, вся концепция интерфейсов - это полиморфизм. (Shape - это интерфейс, определяющий определенное поведение, позволяющий обрабатывать любой тип, реализующий интерфейс Shape в нашем методе). Динамические языки программирования делают это еще глубже, позволяя нам передать в метод любой тип, поддерживающий необходимые действия. Что выглядит лучше для вас: (псевдокод в стиле питона)
def multiply(a,b):
if (a is string and b is int):
//repeat a b times.
if (a is int and b is int):
//multiply a and b
или используя полиморфизм:
def multiply(a,b):
return a*b
Теперь можно использовать любые 2 типа, поддерживающие оператор *, что позволяет использовать метод с типами, которые еще не созданы.
Смотрите полиморфизм, что такое полиморфизм на stackoverflow
Ну, если ты пишешь на Perl, то это просто!
Вместо
if (x) {
# ...
}
ты можешь использовать
unless (!x){
# ...
}
;-)
.Зависит от языка.
Языки со статическими типами должны быть способны обрабатывать все проверки типов, разделяя общие интерфейсы и перегружая функции/методы.
Языки с динамическим набором могут подходить к проблеме по-другому, поскольку тип не проверяется при передаче сообщения, только при доступе к объекту (более или менее). Использование общих интерфейсов все еще является хорошей практикой и может устранить многие из типов проверки на наличие выражений.
Хотя некоторые конструкции обычно являются признаком запаха кода, я не решаюсь устранить любой подход к проблеме априори. Могут быть моменты, когда проверка типов через которые является целесообразным решением.
Примечание: другие предложили использовать switch вместо него, но это просто умный способ написания более разборчивых выражений.
. Идея полиморфизма заключается в том, чтобы вызвать объект без предварительной верификации класса этого объекта.
.
Это не означает, что утверждение if вообще не должно использоваться, следует избегать записи
if (object.isArray()) {
// Code to execute when the object is an array.
} else if (object.inString()) {
// Code to execute if the object is a string.
}
Вы можете сделать это без if
per se, но вы не можете сделать это без механизма, который позволяет вам принять решение, основанное на каком-то условии.
В сборке нет утверждения if
. Существуют условные прыжки.
Например, в Хаскелле нет явного if
, вместо того, чтобы многократно определять функцию, я забыл точный синтаксис, но это что-то вроде:
псевдо-хаскелла:
def posNeg(x < 0):
return "negative"
def posNeg(x == 0):
return "zero"
def posNeg(x):
return "positive"
Когда вы вызываете posNeg(a)
, интерпретатор посмотрит на значение a
, если это < 0
, то он выберет первое определение, если это == 0
, то он выберет второе определение, в противном случае он выберет третье определение по умолчанию.
Таким образом, в то время как такие языки как Haskell и SmallTalk не имеют обычного утверждения в стиле C , если
, они имеют другие средства, позволяющие вам принимать решения.
Хаскелл даже не имеет, если утверждения, будучи чисто функциональными. ;D
Я предполагаю, что вы на самом деле спрашиваете о замене операторов if, которые проверяют типы, в противоположность замене всех операторов if.
Чтобы заменить оператор if на полиморфизм, требующий метода в общем супертипе, вы можете использовать для диспетчеризации, либо непосредственно переопределяя его, либо повторно используя переопределенные методы, как в паттерне посетителя.
Но что делать, если такого метода нет, и вы не можете добавить его к общему супертипу, потому что супертипы не поддерживаются вами? Неужели вы бы действительно пошли на то, чтобы ввести новый супертип вместе с подтипами, просто чтобы избавиться от одиночного if? На мой взгляд, это зашло бы слишком далеко.
Также, оба подхода (прямое переопределение и шаблон посетителя) имеют свои недостатки: Прямое переопределение метода требует, чтобы вы реализовали свой метод в тех классах, которые хотите включить, что может не помочь сцеплению. С другой стороны, шаблон посетителя неудобен, если несколько случаев используют один и тот же код. С помощью if вы можете сделать:
if (o instanceof OneType || o instanceof AnotherType) {
// complicated logic goes here
}
Как бы вы поделились кодом с шаблоном посетителя? Вызвать общий метод? Куда бы вы поместили этот метод?
Так что нет, я не думаю, что замена такого метода, если утверждения всегда являются улучшением. Часто так и есть, но не всегда.
Вы можете определить Истину и Ложь объектами (на псевдо-питоне):
class True:
def if(then,else):
return then
def or(a):
return True()
def and(a):
return a
def not():
return False()
class False:
def if(then,else):
return false
def or(a):
return a
def and(a):
return False()
def not():
return True()
Я думаю, что это элегантный способ построения булеана, и это доказывает, что вы можете заменить каждый if полиморфизмом, но суть анти-иф кампании не в этом. Цель состоит в том, чтобы избежать написания таких вещей, как (в алгоритме поиска пути) :
if type == Block or type == Player:
# You can't pass through this
else:
# You can
но вместо этого вызывать метод is_traversable для каждого объекта. В некотором смысле, это как раз обратная сторона совпадения паттернов. "если" полезно, но в некоторых случаях это не лучшее решение.
.Да, на самом деле, можно иметь полный язык, который не имеет "if" как таковой и допускает только операторы "while":
http://cseweb.ucsd.edu/classes/fa08/cse200/while.html
Что касается дизайна ОП, то в некоторых случаях имеет смысл использовать шаблон наследования, а не переключатели, основанные на поле типа.... Однако это не всегда осуществимо и не всегда желательно.
@ennuikiller: условия были бы просто синтаксическим сахаром:
if (test) body; is equivalent to x=test; while (x) {x=nil; body;}
если-then-else немного более многословен:
if (test) ifBody; else elseBody;
is equivalent to
x = test; y = true;
while (x) {x = nil; y = nil; ifBody;}
while (y) {y = nil; elseBody;}
примитивная структура данных - это список списков. можно сказать, что 2 скаляра равны, если это списки одинаковой длины. Вы бы циклически перебирали их одновременно с помощью операторов head/tail и смотрели, останавливаются ли они в одной и той же точке.
Конечно, все это можно обернуть в макросы.
Самый простой полный язык, который можно выучить, это, вероятно, iota. Он содержит только 2 символа ('i' и '*').
. Ага. если
утверждения подразумевают ветви, которые могут быть очень дорогостоящими на многих современных процессорах - в частности, PowerPC. Многие современные компьютеры делают много переупорядочивания цепочек, и поэтому ошибочные прогнозы цепочек могут стоить порядка >30 циклов за пропущенную цепочку.
.
При консольном программировании иногда быстрее просто выполнить код и проигнорировать его, чем проверить, стоит ли его выполнять!
Простой обход ветки на C:
if (++i >= 15)
{
i = 0;
)
можно переписать как
i = (i + 1) & 15;
Однако, если вы хотите увидеть какую-то реальную анти-if fu, то прочтите это
О, а по вопросу ООП - я заменю неверное предсказание ветки вызовом виртуальной функции? Нет, спасибо....
.Хотя и не связанный с ООП: В Прологе единственный способ написать все ваше приложение - без операторов if
.Я часто писал код по рекомендации в анти-if кампании , используя либо обратные вызовы в словаре делегата, либо полиморфизм.
Это довольно заманчивый аргумент, особенно если вы имеете дело с грязными основами кода, но, честно говоря, хотя он отлично подходит для модели плагина или упрощения больших вложенных если высказываний, он действительно делает навигацию и читабельность немного больно.
Например, F12 (Go To Definition) в визуальной студии приведет вас к абстрактному классу (или, в моем случае, к определению интерфейса).
Это также делает быстрое визуальное сканирование класса очень громоздким и добавляет накладных расходов в настройку делегатов и поиск хэшей.
Использование рекомендаций, выдвинутых в анти-if кампании, насколько они выглядят рекомендуемыми, выглядит для меня как программирование "ооо, новая блестящая штука".
Что касается других конструкций, выдвинутых в этой теме, то, хотя это и было сделано в духе веселого вызова, они просто заменяют "если" заявление, и на самом деле не обращают внимания на то, что лежит в основе анти-if кампании.
.