Но мне почему-то кажется, что, к примеру, для свопа элементов в linked list и array код свопа тоже разный будет
И это тоже нормально. Вот только на примере СиШарпа для Гоу нужно было бы переопределять своп не LinkedList и ArrayList.
А List<Cat>, List<Dog>, List<Animal> и всех остальных листов. Для каждого возможного Т в листе, который мы хотим сортировать нужно определить три метода.
А если мы хотим сортировать ArrayList<Cat> и LinkedList<Cat>, то для каждого из них — тоже заново написать функцию сравнения котов. Понимаете в чём разница?
Это например касается MobX'a, что с ним якобы большие проблемы, пишете что мутирование объекта это bad practice(что вообще просто нелепо) и бла бла бла.
И подписки обзервбла на обзервбл, на что ответ так и не был дан.
когда один observable может быть подписан на изменения другого
А это как? Ну физически как? В MobX есть @observable — свойства на которые там где-то внутри происходит подписка и @computed — свойства, которые подписываются. Вы не подписываете никакие observable на другие observable.
Зачем тогда вы приводите нормальный код на другом языке как контраргумент к существованию пустых интерфейсов, если этот нормальный код в Go будет использоваться точно так же?
Этот код я привожу как объяснение того, что такое полиморфизм. А пустой интерфейс — это аналог типа object. Вы читайте, пожалуйста, внимательнее.
Сравнение типа писать — нормально. Ведь разные типы вполне могут сравниваться одинаково. Да даже в рамках одного типа сравнение может идти по разному. Строки можно сортировать по алфавиту, по длине, по сумме кодов цифр. Обратите внимание, к сравнивателю я не имел претензий.
А вот свап двух элементов массива писать — глупо. Ведь как два элемента массива между собой поменять — совершенно не зависит от наполнения массива. Это глупый, ненужный копипаст. Разницу улавливаете?
Более того, сам по себе сравниватель должен лежать в клиентском коде, возле самих типов. Ведь типов, которые могут лежать в массиве и по которым может происходить сортировка — бесконечное множество и крайне глупо их все описывать в файлике рядом с сортом.
И конкретно это — абсолютно нормальный код. И конкретно это — полиморфизм. Вот только вы говорите сейчас про совершенно другую механику.
Мы обсуждаем необходимость использования пустого интерфейса в Гоу. В обычном коде на других языках вы врядли встретите постоянное использование object или any, а в Гоу — это в порядке вещей.
Я приведу один пример — модуль sort, который написан авторами гоу и который должен сортировать массивы. Он позволяет отсортировать только массивы из нескольких встроенных массивов — тех, что авторы сами лично определили в библиотеке:
type IntSlice []int
type Float64Slice []float64
type StringSlice []string
То есть да, у вас есть три типа, которые вам можно использовать, а остальные — нет.
Более того, код функции Swap в этих трёх типах был просто продублирован три раза. Да, я совершенно серъёзно, они закопипастили один и тот же код три раза. Более того, чтобы расширить возможности этой библиотеки ещё на другие типы — этот код снова надо копипастить для КАЖДОГО типа, который вы хотите поддержать.
В СиШарпе, к примеру, ты можешь сортировать массив из любых элементов, которые реализуют IComparable, ну или передать отдельный IComparer<T> — сравниватель двех элементов.
И, представьте, ничего не копипаститься для каждого нового типа.
Если бы []SomeType удовлетворяло []SomeInterface (при том что SomeType удовлетворяет SomeInterface),
Э нет, всё не так просто. Вы говорите о ковариантности и контравариантности. Нельзя просто так сделать, чтобы оно отвечало, ведь если пойти по одной тропинке — другая будет закрыта.
Ничего я не путаю. Способ указать "тут может быть что угодно" ещё не называется полиморфизмом, как и то, что я могу спрыгнуть с горы ещё не означает, что я умею летать, хотя в воздухе какое-то время я, конечно пробуду. То, что оно в гоу называется красивым словом "interface" ещё не означает, что это сразу стало полиморфизмом, а то, что в TypeScript называется словом any — не стало. Более того, сам по себе полиформизм ещё не означает отсутствие динамики. Полиформизм есть точно так же в полностью динамических языках.
Суть полиформизма в том, что вам не нужно уточнять тип, чтобы с ним работать. Ну, к примеру:
interface IFoo {
void DoSmth();
}
void Method (IFoo foo) {
foo.DoSmth();
}
class Bar : IFoo {};
class Qux : IFoo {};
Method(new Bar());
Method(new Qux());
Вы видите, что я передаю в метод разные типы, но продолжаю с ними работать как с одним. Это — полиморфизм. А вот использовать мета-тип "any" и потом кастить его к нужному типу и получать исключение — это динамика, а не полиморфизм. Ведь проверка и уточнение типа происходит в рантайме, а не в компайл-тайме.
class Foo {
public void Test() {}
}
/**
* Классический строго-типизированный код
*/
public class Static
{
public void Main()
{
Method(new Foo());
}
private void Method (Foo foo) {
foo.Test();
}
}
Далее — динамический код, при передаче в метод непривального аргумента, например Method(new Bar()); ошибка будет не в компайл тайме, как в статически типизированных языках, а в рантайме, как в динамически типизированных языках и да, это динамически типизированный код на C#
public class Dynamic
{
public void Main()
{
Method(new Foo());
Method(new Bar()); // we still can
}
private void Method (object foo) {
((Foo) foo).Test();
}
}
С другой стороны, ещё один гвоздь в гроб экономики советского союза, так что и тут лучше гражданам сделал.
Сглупил. Может подольше жив бы был, если бы приземлил тарелку где нибудь в Техасе. Это был бы самый эпичный побег за всю историю.
Да
Я вас не понимаю. И что? Вы предлагаете не писать код, который должен исполнятся при переходе в статус CANCELLED?
"Если юзер использует наше приложение не так, как задумал программист — он сам дурак", правильно?
Я правильно помню, что это элитный отель, в котором нету туалетов в номерах?
Я бы тогда поднял руку и спросил: "тогда мне ещё непонятно, зачем вы сказали спрашивать тем, кому непонятно?"
Есть ещё одна — "я нифига не понял, потому на всякий случай минус"
Почему из
order->cancel()
хоть как-то следует копипаста?И это тоже нормально. Вот только на примере СиШарпа для Гоу нужно было бы переопределять своп не
LinkedList
иArrayList
.А
List<Cat>
,List<Dog>
,List<Animal>
и всех остальных листов. Для каждого возможного Т в листе, который мы хотим сортировать нужно определить три метода.А если мы хотим сортировать
ArrayList<Cat>
иLinkedList<Cat>
, то для каждого из них — тоже заново написать функцию сравнения котов. Понимаете в чём разница?И подписки обзервбла на обзервбл, на что ответ так и не был дан.
А это как? Ну физически как? В MobX есть
@observable
— свойства на которые там где-то внутри происходит подписка и@computed
— свойства, которые подписываются. Вы не подписываете никакие observable на другие observable.Этот код я привожу как объяснение того, что такое полиморфизм. А пустой интерфейс — это аналог типа
object
. Вы читайте, пожалуйста, внимательнее.Сравнение типа писать — нормально. Ведь разные типы вполне могут сравниваться одинаково. Да даже в рамках одного типа сравнение может идти по разному. Строки можно сортировать по алфавиту, по длине, по сумме кодов цифр. Обратите внимание, к сравнивателю я не имел претензий.
А вот свап двух элементов массива писать — глупо. Ведь как два элемента массива между собой поменять — совершенно не зависит от наполнения массива. Это глупый, ненужный копипаст. Разницу улавливаете?
Более того, сам по себе сравниватель должен лежать в клиентском коде, возле самих типов. Ведь типов, которые могут лежать в массиве и по которым может происходить сортировка — бесконечное множество и крайне глупо их все описывать в файлике рядом с сортом.
И конкретно это — абсолютно нормальный код. И конкретно это — полиморфизм. Вот только вы говорите сейчас про совершенно другую механику.
Мы обсуждаем необходимость использования пустого интерфейса в Гоу. В обычном коде на других языках вы врядли встретите постоянное использование object или any, а в Гоу — это в порядке вещей.
Я приведу один пример — модуль
sort
, который написан авторами гоу и который должен сортировать массивы. Он позволяет отсортировать только массивы из нескольких встроенных массивов — тех, что авторы сами лично определили в библиотеке:То есть да, у вас есть три типа, которые вам можно использовать, а остальные — нет.
Более того, код функции Swap в этих трёх типах был просто продублирован три раза. Да, я совершенно серъёзно, они закопипастили один и тот же код три раза. Более того, чтобы расширить возможности этой библиотеки ещё на другие типы — этот код снова надо копипастить для КАЖДОГО типа, который вы хотите поддержать.
В СиШарпе, к примеру, ты можешь сортировать массив из любых элементов, которые реализуют
IComparable
, ну или передать отдельныйIComparer<T>
— сравниватель двех элементов.И, представьте, ничего не копипаститься для каждого нового типа.
Э нет, всё не так просто. Вы говорите о ковариантности и контравариантности. Нельзя просто так сделать, чтобы оно отвечало, ведь если пойти по одной тропинке — другая будет закрыта.
Вот именно!
И при ошибке типа будет что?
Правильно, ошибка в рантайме.
А ошибка в рантайме при неправильном типе у нас в каких языках?
Правильно, динамических!
А нафига такую хрень вообще использовать?
Правильно, потому что нету дженериков.
Я рад, что мы с вами сошлись.
Ничего я не путаю. Способ указать "тут может быть что угодно" ещё не называется полиморфизмом, как и то, что я могу спрыгнуть с горы ещё не означает, что я умею летать, хотя в воздухе какое-то время я, конечно пробуду. То, что оно в гоу называется красивым словом "interface" ещё не означает, что это сразу стало полиморфизмом, а то, что в TypeScript называется словом any — не стало. Более того, сам по себе полиформизм ещё не означает отсутствие динамики. Полиформизм есть точно так же в полностью динамических языках.
Суть полиформизма в том, что вам не нужно уточнять тип, чтобы с ним работать. Ну, к примеру:
Вы видите, что я передаю в метод разные типы, но продолжаю с ними работать как с одним. Это — полиморфизм. А вот использовать мета-тип "any" и потом кастить его к нужному типу и получать исключение — это динамика, а не полиморфизм. Ведь проверка и уточнение типа происходит в рантайме, а не в компайл-тайме.
Далее — динамический код, при передаче в метод непривального аргумента, например
Method(new Bar());
ошибка будет не в компайл тайме, как в статически типизированных языках, а в рантайме, как в динамически типизированных языках и да, это динамически типизированный код на C#