>задачи по ООП
Wtf is this? Вопросы типа "как применять костыль "команда" и "наблюдатель" для замены ферст-класс функций и системы событий"?
>>345680
Нет, практические вопросы типа "Есть один проект. Я сделал так, так и вот так, теперь я хочу поменять вот эту поебень и сломалось что-то внутри черепа".
Спектр языков максимально большой, где ООП есть, а монд нет. От C++ до псевдокода.
Как реализовать в питоне комбинатор неподвижной точки?
Какой из диалектов лиспа выбрать?
>>345686
Возьму пики точеные, срублю хуи дроченые,
а потом проснусь же.
Короче, как будут вопросы, задавайте.
(defmacro -> (val f &rest fs)
(cond ((null fs)
(cond
((listp f) `(funcall ',(car f) ,val ,@(cdr f)))
(t `(funcall ',f ,val))))
(t `(-> (-> ,val ,f) ,@fs))))
>>345686
fix = lambda f: (lambda x: f (lambda y: x (x) (y))) (lambda x: f (lambda y: x (x) (y)))
>>345701
Весь раздел заполнен только дегенератами-холиварщиками, чтоли? Ну предположим я разберусь в том, что здесь написано. Ну да, какой-то макрос. Ты даже не представляешь, как сильно мне насрать. Ты даже не задал вопрос. Не обосрался ли я. Это и есть твой вопрос? Нет, не обосрался.
>>345709
Это макрос из Кложуры реализованный в Коммон лиспе, в котором нет гигиены. Из-за того, что гигиены нет при раскрытии может произойти конфуз, вот я и спрашиваю, не обосрался ли я?
И у меня встречный вопрос к любителю комбинаторов неподвижной точки. Предложи всего-лишь один правдоподобный пример, где эти знания пригодятся (кроме собеседования и хелловордов).
>>345714
Мемоизирующий комбинатор неподвижной точки позволяет удобно мемоизировать произвольную функцию.
>>345713
Увлекался только схемой когда-то и уже всё забыл.
Мне лично не ясен синтаксис там, где funcall,
хотя я потратил некоторое время на гугление.
макрос val (f, fs = null)
{
if (fs это null)
{
if (f это ConsCell)
{
return что-то одно;
}
else
{
return [true, [что-то другое]];
}
}
else
{
return что-то третье;
}
}
Написал функцию, складывающую матрицы, получилось некрасиво.
ОП, как переписать, чтобы было красиво.
Функция:
list(map(lambda x: list(x), list(map(lambda x, y: map(lambda a, b: a + b, x, y), matrix1, matrix2))))
Матрицы записываются так: [[1, 3, 4], [6, 3, 5], [9, 4, 2]]
>>345728
Ах да, по поводу ООПа:
Я хочу создать класс Matrix, и перезагрузить для него сложение.
Как мне передать в метод два списка? с помощью *arg ведь только один можно передать?
>>345730
list(map(lambda x: list(x), list(map(lambda x, y: map(lambda x, y: x + y, x, y), x, y))))
Переименовал аргументы, чтобы покрасивше было. Но как сделать более красивой саму структуру функции? Мне кажется, я тут делаю какие-то ненужные вызовы, которые можно сократить.
Что думаешь, ОП?
Ну и как мне передать в метод два списка?
>>345730
Проявлю себя как типичный джавист (хотя это не правда) и скажу, что что-то здесь неправильно, и излишний *arg вреден. И по закону жанра, я сразу должен сравнить программиста, текущего по синтаксису, с лингвистом.
Ты хочешь класс Matrix. С чем он должен складываться? С другой матрицей.
Matrix
-------------
конструктор(ширинаСтроки, List<Float>)
конструктор(ширинаСтроки, элемент1, элемент2...)
плюс(matrix:Matrix)
Matrix m = new Matrix(3,1,2,3,4,5,6,7,8,9).plus(new Matrix(3,1,2,3,4,5,6,7,8,9));
// Если можно переопределять операторы:
Matrix m = new Matrix(3,1,2,3,4,5,6,7,8,9) + new Matrix(3,1,2,3,4,5,6,7,8,9);
Matrix
-------------
конструктор(ширинаСтроки, List<Float>)
конструктор(ширинаСтроки, элемент1, элемент2...)
static sum(m1:Matrix, m2:Matrix)
>>345735
>Matrix m = new Matrix(3,1,2,3,4,5,6,7,8,9).plus(new Matrix(3,1,2,3,4,5,6,7,8,9));
Так я и сам мог догадаться. Я спрашивал про красивое решение.
>>345736
Скажи мне, в каком контексте используется этот матрицеобработчик.
>>345738
Я занялся изучением питона. Сейчас читаю про перегрузку операторов. Чтобы попрактиковаться, решил написать класс для работы с матрицами, и перегрузить для него основные арифметические операторы.
>>345739
Питон слабоват по части обучения ООП. Никогда не знаешь,
какого класса аргумент прилетел. Слышал, что там сейчас
можно указывать типы аргументов, но они
всё равно не проверяются.
Ну, вот так же красиво выглядит. Разве нет?
m = Matrix([[1,2,3],[4,5,6],[7,8,9]]) + Matrix([[1,2,3],[4,5,6],[7,8,9]]);
конструктор(List<List<Float>>);
IMatrix
-----------------
плюс(matrix:IMatrix)
-----------------
IMatrixFactory
-----------------
get(values:List<List<Float>>) : IMatrix
get(values:List<List<Int>>) : IMatrix
-----------------
>>345725
Я ничего в этом не понимаю, но ты победил.
Мемоизация бывает очень полезна.
Хотя с другой стороны, можно ее сделать,
ничего не понимая в математике.
Конкретно в питоне это делается за 2 минуты
без использования мозгов вообще.
my_func_memo = dict()
def my_func(a):
def inner(a):
# здесь все расчеты
if (a in my_func_memo):
return my_func_memo[a]
else:
my_func_memo[a] = inner(a)
return my_func_memo[a]
#случай с несколькими параметрами
my_func_memo = dict()
def my_func(a,b,c):
def inner(a,b,c):
# ...
if ((a,b,c) in my_func_memo):
return my_func_memo[(a,b,c)]
else:
my_func_memo[(a,b,c)] = inner(a,b,c)
return my_func_memo[(a,b,c)]
>>345679
Посоны помогите с задачкой на джаве
Исправьте ошибки: переместите методы clone в те классы, в которых они должны быть реализованы.
Лишние методы удалите.
public class Solution {
public static class A implements Serializable {
}
public static class B implements Remote {
}
public static class C extends ArrayDeque {
}
public static class D implements EventListener {
}
protected A clone() throws CloneNotSupportedException {
return (A) super.clone();
}
protected Thread clone() throws CloneNotSupportedException {
return (Thread) super.clone();
}
protected final B clone() throws CloneNotSupportedException {
return (B) super.clone();
}
protected ArrayDeque clone() throws CloneNotSupportedException {
return super.clone();
}
public C clone() {
return (C) super.clone();
}
protected D clone() throws CloneNotSupportedException {
return (D) super.clone();
}
}
>>345796
Ты! Ты понимаешь, что у тебя проблема с тем, чтобы говорить? Чтобы другой человек что-то понял, ты должен сначала что-то сказать! Это нормально для имиджборд, в этом нет ничего страшного, здесь почти все такие.
>>345796
Первый раз слышу, чтобы один класс мог иметь несколько методов clone в джаве. Метод clone - он клонирует текущий объект, который этого класса.
А интерфейсы-маркеры - это вообще о другом. Если бы был некий посторонний класс, который может обрабатывать некие объекты, то в нем может быть внутри метода проверка, реализует ли объект какой-то интерфейс. Если да, то сделать так, а если нет, то сделать эдак. А что ты в коде написал, я вообще понять не в силах.
Ну ёба че непонятного то? Реализации никакой нет. Код абстракция. Из 6 методов clone() нужно выкинуть все те которые не подходят ни одному из 4 классов (ABCD), а те которые подходят (логически) переместить внутрь классов. Сформулировав по-другому, если бы вам нужно было реализовать метод clone() внутри классов ABCD какие бы методы из представленных вы бы туда добавили не меняя сигнатуры классов\методов?
>>345813
Не пизди. Реализации нет. Еще как есть.
У всех методов clone ты сделал реализацию. И что же там внутри? Они вызывают родительский элемент. Какой?! Ты что, ебанулся? Класс Solution не наследует никакие классы. Это во-первых. Во-вторых. Метод clone здесь использовать нельзя, т.к. у него в java другое значение. Clone - клонирует объект от которого вызывается. Это два. Возвращаемое значение в java не является частью сигнатуры метода. Т.е. если это скомпилируется, я скажу "Уау, 4 одинаковых метода! И оно работает!". Это три. И в-четвертых, ты вообще походу не понимаешь, что делаешь. Это если уж говорить не про java, а вообще.
Такое чувство, что я повелся на какой-то ужасный троллинг.
Такое запоздалое чувство, что это задачка из собеседований для джавистов.
Написал в соседнем треде и потом только увидел этот. Вот:
Мне тут в голову пришло, что полиморфизм и наследование часто противоречат друг другу. Смотри, анон. Наследование - здесь основная концепция в том, что предок может расширять родительский класс. То есть не только изменять его, но и добавлять своё уникальное поведение (свои собственные методы). А вот полиморфизм позволят объекту выступать в ипостаси своего родителя. То есть потомок - это частный случай своего предка, поэтому он должен сохранить свою совместимость с ним. Разве это не взаимоисключающие случаи?
>>345832
Поэтому для полиморфизма используют интерфейсы, анон. А наследование позволяет не переписывать заново повторяющееся поведение, повторяющиеся методы.
>>345836
Получается, что если мне нужен этот частный случай полиморфизма (возможность смотреть на разные объекты и видеть одну и ту же сущность), я должен обращаться к нему через интерфейс? Вот так к примеру:
List<String> list = new ArrayList<>();
list = new LinkedList<>();
>>345844
>я должен обращаться к нему через интерфейс?
Везде, где возможно, следует работать с объектами через интерфейсы. Если вся работа с объектом от создания до уничтожения (если таковое в языке явно указывается) идет в одном методе, нет ничего плохого, чтобы писать
ArrayList<String> list = new ArrayList<String>();
. Но если значение куда-то уходит из метода или если это наоборот аргумент метода, он должен быть обозначен интерфейсом. Это повод задуматься, если где-то не так. Я не исключаю такой возможности, что иногда нельзя не делать по-другому.list = new LinkedList<>();
>>345821
Всё разобрался. Правильным решением было
public class Solution {
public static class A implements Serializable {
}
public static class B implements Remote {
}
public static class C extends ArrayDeque
{
public C clone() {
return (C) super.clone();
}
}
public static class D implements EventListener {
}
}
>>345747
Но ведь в питоне нет интерфейсов. Можно, конечно, подключить их из модулей, но хотелось бы по возможности тянуть минимальное количество зависимостей.
>>345873
Плохо, что нет, на мой взгляд. Только почитай. Тут пишут, что это не Python way. Как же иначе писать большое ПО на питоне, я не знаю. http://stackoverflow.com/questions/5856963/abstract-methods-in-python
Вернее как вообще писать большое ПО иначе, я не знаю.
>>345891
Наверное, на нем и не надо писать большое ПО. Я его выбрал для изучения программирования, потому что он имеет низкий порог вхождения, и поддерживает самые разные парадигмы, пусть и не полностью.
>>345892
А я ведь даже делал пожертвования в PyPy. Сейчас не помню сколько, тысячи три рубчинских. А сейчас обхожу стороной.
>>345679
Аноны, выручайте, есть задача на Java и код:
В таблице есть колонки, по которым можно сортировать.
Пользователь имеет возможность настроить под себя список колонок, которые будут сортироваться.
Напишите public static компаратор CustomizedComparator, который будет:
1. в конструкторе принимать список компараторов
2. сортировать данные в порядке, соответствующем последовательности компараторов.
Все переданные компараторы сортируют дженерик тип Т
В конструктор передается как минимум один компаратор
*/
public class Solution {
public static class CustomizedComparator<T> implements Comparator<T>{
List<Comparator<T>> list;
public CustomizedComparator(Comparator<T> ... cmp)
{
Collections.addAll(this.list, cmp);
}
@Override
public int compare(T o1, T o2)
{
return list.indexOf(o2)-list.indexOf(o1);
}
}
}
>>346084
Вот так ещё решил, всё равно не проходит:
public class Solution {
public static class CustomizedComparator<T>{
ArrayList<Comparator> list;
public CustomizedComparator(Comparator<T> ... cmp)
{
if (cmp.length>0) Collections.addAll(this.list, cmp);
Comparator<Comparator> compareByIndex=new Comparator<Comparator>()
{
@Override
public int compare(Comparator o1, Comparator o2)
{
return list.indexOf(o2)-list.indexOf(o1);
}
};
Collections.sort(list,compareByIndex);
}
}
>>345680
>команда
Прочитал как "монада", вспомнил, что это ООП тред и проиграл.
Объясни мне, что такое замыкание и dependency injection. Википедию читал, но так и не понял - то ли это что-то такое очевидное, что везде есть, все его используют, не называя это этими словами, то ли это что-то сложное, и я хуй знает, что это.
>>346097
И даже так:
public class Solution {
public static class CustomizedComparator<T> implements Comparator<Comparator<T>>{
public ArrayList<Comparator<T>> list;
public CustomizedComparator(Comparator<T> ... cmp)
{
if (cmp.length>0) Collections.addAll(this.list, cmp);
}
@Override
public int compare(Comparator<T> o1, Comparator<T> o2)
{
return list.indexOf(o1)-list.indexOf(o2);
}
}
}
>>346102
Замыкание - это одно.
Dependency injection - это другое.
Объясню про второе. Смотри.
Ты делаешь некий класс A, которому нужен объект класса/интерфейса B.
Как поступает Ерохин, когда делает класс А? Он берет и создает внутри него (в конструкторе, допустим) объект B. Не. Я неправильно объясняю. Бля.
Смотри.
Когда работаешь, у тебя есть много разных ситуаций. И в джаве ведь всё является классом, но при этом некоторые классы - они как ключевые точки программы. Как основные модули. Ты понимаешь, что всегда каждый из них нужен будет только в одном экземпляре. Допустим, ты пишешь игру, и у тебя много ее кусков - графон, AI, какая-нибудь другая хрень, и несмотря на то, что тебе может понадобиться из одного куска что-то делать с другим куском, тебе не нужно в каждом куске заново создавать все другие куски, тебе не нужно два графона, пять модулей какой-то другой хрени и т.д. А все эти модули или куски программы - это ведь обычные объекты.
Короче, принцип выворачивание контроля (inversion of control) - это когда те объекты, которые нужны для класса, создаются не в самом классе, а потом выносятся наверх, а наоборот создаются сверху и внедряются внутрь. И отсюда название - Dependency injection - объекты, от которых зависит некоторый другой объект - они создаются не в нем, а снаружи от него, и внедряются в него (через сеттеры, например). На логическом верхе программы создаются все части программы и внедряются друг в друга, потому что они зависят друг от друга. Вот. Смотри пример http://cube54.tk/oopro/1 Здесь программа на JS разрывается на четыре куска так, что три из них сами по себе и отдельно друг от друга, а один что-то делает с html.
А за счет того, что сеттеры принимают объект как интерфейс, а не реализацию, в месте сборки можно легко поменять одну реализацию на другую. Например, у тебя есть объект, который выдает данные. Ты пишешь программы и делаешь его как заглушку - Mock-объект. Но когда приходит время писать настоящую реализацию, не обязательно удалять Mock. Ты херачишь unit-тесты, и делаешь так, что в тестовой конфигурации у тебя этот Mock и используется, а в обычной сборке подключается класс, который лезет в БД.
>>346102
Короче это как раз очень простое и очевидное, но эту очевидность просто нужно прочувствовать.
>>345847
Спасибо большое, все понятно написал, вроде стало яснее, кроме:
>Если вся работа с объектом от создания до уничтожения идет в одном методе, нет ничего плохого, чтобы писать
>ArrayList<String> list = new ArrayList<String>();
А если, как я уже писал выше, я ещё добавляю поведение в класс, который итак полностью реализует интерфейс. Ничего плохого, чтобы работать с ним так же, как выше. Или это уже признак плохой архитектуры?
>>345848
>Что ты этим хотел сказать?
Не знаю, я до Java-коллекций еще не добрался. Просто хотел показать, что так тоже можно работать с объектами.
>Наркоман? В InputStream есть интерфейс(его public методы) и даже абстрактный метод read().
Я имел ввиду интерфейс не в широком смысле, а interface в Java. А вот read()/write() методы, мне казалось, лучше вынести в отдельный interface.
ОП, расскажи, что такое проксирование и как оно связано с инкапсуляцией.
И ещё. ОП, как ты можешь понимать ООП отдельно от какого-то языка программирования? Ведь у ООП нету четкой концепции и каждый язык описывает её по-своему.
>>346102
>замыкание
Знаешь, что такое лямбда? Вот это почти одно и то же. Допустим, у тебя есть функция ф1
, которая содержит две переменные а
и б
. Ты в этой функции "создаёшь" другую функцию ф2
, которая содержит переменную в
. В этот момент происходит то самое замыкание, функция ф2
запоминает значения а
и б
, и теперь может обращаться ко всем трём переменным, хотя внутри неё объявлена только одна.
>dependency injection
Допустим, ты делаешь игру. У тебя есть объект движок
, и есть объект графическийДвижок
, у которого есть функция нарисоватьКартинку
. Обычно ты бы в конструкторе объекта движок
создавал бы графическийДвижок
, а потом рисовал бы им. Неплохой способ, но если тебе захочется потом поменять отрисовщик (чтобы он был на опенгл, например), то тебе придётся лезть в конструктор и менять там, а если твой движок будет в виде библиотеки, то это будет вообще невозможно (если кто-то другой захочет сменить, например). Решение - выбросить создание объекта графическийДвижок
из конструктора движка, и вместо этого требовать его параметром, например, того же конструктора. Теперь пользователи могут воткнуть туда вообще всё, что угодно, до тех пор, пока оно имеет метод нарисоватьКартинку
.
>>346137
>функция ф2 запоминает значения а и б, и теперь может обращаться ко всем трём переменным, хотя внутри неё объявлена только одна.
То есть, получается, что каррирование — частный случай замыкания?
lambda x: lambda y: lambda z: x + y + z
Последняя лямбда замыкается на первые две, так?
>>346131
> у ООП нету четкой концепции
У мамаши твоей нету четкой концепции. Читай Б. Мейера и просвещайся, быдло.
каталог-кун пишет:
современое ООП:
толпы быдла долбятся головами об стену невидя двери -
для них выпиливают люк.
http://openpaste.org/482Efbd3
http://ideone.com/E07a2
>>345686
Он там не нужен.
>>345730
Ты задания с кодакадемии решаешь?
>>345747
> Ну, вот так же красиво выглядит. Разве нет?
>
> m = Matrix([[1,2,3],[4,5,6],[7,8,9]]) + Matrix([[1,2,3],[4,5,6],[7,8,9]]);
Красиво должно выглядеть так:
m = [1 2 3; 4 5 6; 7 8 9] + [1 2 3; 4 5 6; 7 8 9]
В нампай эти matrix нинужны, но строки всё равно вставляются коряво.
>>345754
Да тебя троллят. В пайтоне Y-комбинаторы не нужны.
>>346150
Твой пример верен.
>>346137
Ну так это просто скоупы. Разве есть языки без этого?
>>346262
Это как -> только место куда будет вставлен аргумент в каждой форме задаётся отдельно:
(as-> "myfile.txt" x
(slurp x)
(str "[" x "]")
(read-string x))
>>346141
Нет, вот как надо объяснять Dependency Injection:
Потный мальчик Никита внедрил Танюше ребенка.
Но это мог быть и не Никита, а мачо-мальчик Бахтияр.
Тане неважно, она всё равно любит дитятю одинаково.
>>346131
> ООП отдельно от языка
Вещает оп. Я считаю каноничным ООП тот, которому учили в школе, который рисуют в UML-диаграммах и защищают на дипломе. Он каноничный не потому что так изначально придумали, а потому что используется в продакшне, хуё-моё.
>проксирование, инкапсуляцией
Да шкет его разумеет. Когда проксируют что-то, его же не частями проксируют. Вот и инкапсуляция тебе. Если мы говорим об одном и том же. Вот например в Spring'е для АОП используются Прокси-объекты.
Действует это вот как. У тебя есть класс с какими-то методами, и ты пишешь какую-то херотню над ними, вроде @делаетТоТо. Эти аннотации естественно нихера не работают сами по себе. Но когда этот объект внедряется в другой объект через Autowired, внедряется на самом деле Proxy-объект, который мимикрирует под этот объект этого класса, и при вызове тех же методов делает что-то еще дополнительно. Так что это относится скорее к полиморфизму, а не к инкапсуляции.
>>346441
>Действует это вот как. У тебя есть класс с какими-то методами, и ты пишешь какую-то херотню над ними, вроде @делаетТоТо. Эти аннотации естественно нихера не работают сами по себе. Но когда этот объект внедряется в другой объект через Autowired, внедряется на самом деле Proxy-объект, который мимикрирует под этот объект этого класса, и при вызове тех же методов делает что-то еще дополнительно. Так что это относится скорее к полиморфизму, а не к инкапсуляции.
Это относится к жалкой попытке компенсировать отсутствие макросов.
>>346504
Позволю себе возразить. Макросы, хоть и нужны, чтобы читаемость улучшалось, обычно ее ухудшают. А аннотации в спринге работают предсказуемо вполне, и читаемости не вредят.
>>346504
И вообще, как бы ты сделал адекватный АОП через макросы?
>>346528
> Позволю себе возразить. Макросы, хоть и нужны, чтобы читаемость улучшалось, обычно ее ухудшают.
Не знаю, что ты подразумеваешь под "обычно", но все макросы в clojure.core читабельность улучшают.
> А аннотации в спринге работают предсказуемо вполне, и читаемости не вредят.
Предсказуемо, это когда прямо в репле можно сделать macroexpand и увидеть, во что преваращается код. А не когда нужно лезть в сорцы каких-то annotation processor-ов
>>346529
Ну начнём с того, что концепцию АОП развил лиспер Gregor Kiczales. Не знаю, что ты понимаешь под "адекватным АОП", но в реальном коде я натыкался только на что-то соответствующее макросам with-logging, with-transaction и т.д. Это примерно 0.01% реальной силы макросов.
>>345679
Чем отличается абстрактный класс от интерфейса?
Тред не читал
>>346570
В интерфейсе только заголовки методов (это практически по определению), в абстрактном классе есть реализованные члены и несколько заголовков.
>>346576
ААААААА ХУЙ СОСИ ЛОШАРА
http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
Пикрилейтед - то, во что превратился этот тред. Поэтому, посоветуйте, чего бы такого купить пожрать. Думал купить огромные чипсы, но я итак хаваю только жареную картошку последние несколько дней. Какие будут предложения?
>>346601
макороны с сыром хорошо пойдут
ты слишком много жиров еш
пельмени не рекомендую
>>346616
В сыре тожн жиров дохера. Пусть гречки навернет без нихуя с соевчм соусом.
категория: платиновые треды /pr/
>>346533
Читаемость улучшают только те макросы, про которые все работники знают. Так что это должна быть какой-то общепринятый набор макросов, чтобы разработка в команде была возможна. Надеюсь, тред не съедет в священовойны, так или иначе.
> в репле можно сделать macroexpand и увидеть, во что преваращается код. А не когда нужно лезть в сорцы каких-то annotation processor
В джаве код не меняется же. А понять, что происходит можно либо из дебаггера, либо во всех современных IDE жмешь по аннотации, удерживая ctrl, там стопудово приложена документация. В спринге так. Написано, иди туда, сканер там. Короче, всё это пустое, мелочи.
>>346629
Гречку я тоже купил, не расстраивайся, бро, бро.
>>345679
В чем разница между абстрактным классом и интерфейсом?
>>346703
Я уже рассусоливал на эту тему.
Вот здесь: >>345847
После строчки
>Почему в java.io.* InputStream и OutputStream - это абстрактные классы?
В чем разница, в википедии прочитаешь, а использовать вместо интерфейса абстрактный класс можно вполне, но только когда в этом есть смысл. Лучше этого не делать.
>>346703
Интерфейсы - это то, с чего должна начинаться разработка любой ООП-программы. Потом они обрастают реализациями. Абстрактные классы появляются уже в процессе работы, в результате рефакторинга, например, или просто, чтобы сэкономить время, не повторять код.
>>346703
Абстрактный класс - это лучший способ сделать наследование без хуйни, не нарушая принцип единственной обязанности.
>>345680
В некоторых ООП-языках есть first-class-функции, которые передаются как ссылки на методы объектов и статические методы. Такие языки можно воспринимать, как химеры, хотя и нет ничего противоестественного вроде. При таком подходе без сборщика мусора то не обойтись. Один из языков, по которому я последнее время угорел - Haxe3 - могёт в такие вещи, и переданные функции в нем сохраняют проверку типов. Но мне на эту фичу по большому счету класть. Понятия не имею, насколько нечитаемый код для крестов он выдает.
(defmacro as-> (val sym f &rest fs)
(cond ((null fs)
(cond ((listp f) `(funcall ',(car f) ,@(substitute val sym (cdr f))))
(t `(funcall ',f ,val))))
(t `(as-> (as-> ,val ,sym ,f) ,sym ,@fs))))
(defmacro <_ (&rest args)
(with-gensyms (new-args)
(let ((new-args (nreverse args)))
`(as-> ,(car new-args) _ ,@(cdr new-args)))))
>>346727
Поправил, чтоб лямбды можно было использовать http://ideone.com/7tzrB9
Наверное, все-таки стоит имена функций передавать с апострофом...
категория: платиновые треды /pr/
>>346703
> The most obvious difference between the two mechanisms is that abstract classes are permitted to contain implementations for some methods while interfaces are not. A more important difference is that to implement the type defined by an abstract class, a class must be a subclass of the abstract class.
Effective Java
Item 18: Prefer interfaces to abstract classes
Key.unlock(lock) или lock.unlock(key)
>>349570
KeyProviderFactory keyProviderFactory = new KeyProviderFactory();
KeyProvider keyProvider = keyProviderFactory.getKeyProvider();
Key key = keyProvider.getKey();
LockProviderFactory lockProviderFactory = new LockProviderFactory();
LockProvider lockProvider = lockProviderFactory.getLockProvider();
Lock lock = lockProvider.getLock();
OpenerManagerFactoryProvider openManagerFactoryProvider = OpenerManagerFactoryProvider.getInstance();
OpenManagerFactory openManagerFactory = openManagerFactoryProvider.getOpenManagerFactory();
OpenLockWithKeyManager openLockWithKeyManager = openManagerFactory.getManager<OpenLockWithKeyManager>( OpenLockWithKeyManager.Class );
openLockWithKeyManager.openLockWithKey( lock, key );
конечно же.
>>345726
Про Dependency Injection, ты имеешь в виду заменить без перекомпиляции, как это делается в Spring?
>>349570
Очевидно, второе, т.е. Lock - это наследник некой абстрактной сущности Entity, к которой можно применять предметы. В частности к Lock можно применить предмет Key.
>>345679
Суп, ОП. Поясни простым языком за 3 принципа ООП. И на счет интерфейсов: как правильно их использовать?
>>349668
Первый принцип ООП - в 1с нет ООП.
Второй принцип ООП - что бы они не говорили, ООП не в 1с.
Третий принцип ООП - ООП 1с в не.
>>349706
>{1c, нет, ООП}
Перебрал множество и радуется. Хуею с долбоеба. Поясни за принципы ООП, лалка. Может на что-то сгодишься.
>>349739
наследственая полиморфизьма инкапапуляция, я принят?
>>349742
>я принят?
Нет, ты долежен сначала разъяснить эти принципы простыми словами.
>>349764
пихание одних структур в другие, создавание отдельных функций на каждый тип данных, сокрытие реализации
хотя есть и другие способы реализовать ООП, но именно так в плюсах
Не 349742-кун
>>346668
Теперь в интерфейсе могут быть методы. Отличие от абстрактного класса в том, что все методы public и\или static
>>345679
Один крестопогромист говорил что при создании игор обычно делают рендер отдельно от самой игры. В рендере делают сцену, возможность размещать на сцене разные модельки, свет и тому подобное. Потом передают моделькам на цене реальные координаты игровых объектов. Вроде вполне решаемая задача - создаём класс модели, в нем делаем указатель на координаты, возможность передать ему ссылку на координаты игрового объекта. Но дальше проблемы появляются:
А если эта модель не привязана к игровому объекту? Тогда выделять память и создавать её личные координаты? А если захотим потом её привязать к игровому объекту? А если потом мы удалим этот игровой объект? Как оповестить модель на сцене об этом?
Это я что-то не так додумал, или это все вполне решаемо и не похоже на костыли?
>>350193
Что ты хочешь вообще?
У тебя есть список моделей, которые грузятся при старте игры / при старте уровня. Он заранее подготавливается игровым редактором.
Каждая графическая модель, очень грубо говоря, это кусок бинарных данных (блоб), содержащий вершины и их индексы. При загрузке эти данные заливаются в видеопамять с помощью графического Api (e.g. OpenGL ES). То есть, модель содержит в себе ИД вершинного, индексного буферов в видеопамяти, смещения от начала буферов, размер участка в вершинном/индексном буфере, принадлежащего модели, ИД текстуры и шейдера, которые используются для отрисовки.
У игрового объекта может быть ссылка на графическую модель, которая отвечает за его показ на экране, collision модель ( упрощенная модель — шар, коробка или низкополигональный выпуклый многогранник, и их иерархические комбинации ), которая используется для расчета столкновений, и многое другое.
>>350198
То есть данные render, collision моделей и иные игровые данные находятся всегда в памяти и загружаются/выгружаются только при смене уровня/запуске приложения. Игровой объект может ссылаться на них, чтобы его показали/просчитали столкновения, и т.д.
>>350200
Это то мне понятно, я хочу сделать рендер и игру не зависимыми совсем. Хочу - использую рендер напрямую без всяких игр. Хочу - с игрой. Чтобы он сам разбирался где отображать модели. Чтобы рендер про игру ничего не знал. То есть рендер знает что там-то надо одну модель нарисовать, ещё где-то другую. А так получается придётся в игровых объектах(монстрах, игроке, стенах и прочем) делать метод для получения координат, пихать все это в рендер и указывать какую модель в них рисовать. А если я захочу сделать йоба сортировку объектов, чтобы не рисовать то, чего не видит камера? Причём в самом рендере. Т.е. игра просто должна сказать рендеру что он должен сколько-то как-бы отображаемых объекта в определённых координатах создать(и внезапно это координаты существующих в игре объектов, а может и нет). Я передвинул игрока - координаты изменились, а эти же самые координаты используются отображаемым объектом. Надо как-то сказать рендеру что они поменялись. Рендер сам как-то разберется что ему с ним делать. Может ему вообще все равно, а может он проверит видит ли его камера. Зависит от того что я сделаю. А игры это не касается.
Ну и бамп.
>>350193
Это не только не костыли, это так и должно быть.
>>350200
Вот это уже похоже на костыли. Нахуй так жить? Вещи, которые не нужны постоянно, не должны висеть в памяти постоянно, и нахуй не нужны ссылки из физ. модели в графическую. Не проще ли сделать так:
1. Игровой объект - то, на чем основана игровая механика - персонаж, футбольный мяч, стена, шкаф, здание. Если персонаж, то со скелетом, если другой объект, с collision-моделью, наборами действий, если дом, тоже с коллижинами, стенами, дверьми. Фактически, он должен быть и основой для физики и возможностей взаимодействия предметов между собой в игровом мире (НЕ считая управления пользователя, который должен считаться просто одним из персонажей, иначе это дебилизм).
Делаешь у игровых объектов hashcode, не зависящий от состояния, вида return this.id.
2. Графический объект - только данные для отрисовки.
Мы всегда можем сделать графический из игрового. За это доллжен отвечать специальный модуль (3). Например, у тебя есть контры и терроры, как в CS. Ты можешь в этом модуле менять им скины, модели и вообще всё, касающееся внешнего вида. Естественно это работает не очень моментально. Графический объект тоже НЕ должен ссылаться на игровой, потому что это дебилизм.
Делаешь несколько видов таких штук. Например, если это person, у него наверняка есть скелет, да и не только (вибропоказатель сисек, оттопыривание правой губы), если это трава, ее колыхание нужно жестко контролиировать одним-двумя свойствами.
Слушай дальше.
Итак, у тебя есть объекты 1 и 2. Тебе нужен класс, преобразующий 1 в 2.
Делаешь его и выносишь за пределы модулей 1 и 2, встраиваешь в него кэш.
Это всё будет в модуле 3, зависимом от 1 и 2.
Чтобы кэш работал адекватно, ему нужно скармливать все камеры,
между которыми ты будешь переключаться. Если ты этого не сделаешь,
он будет всегда непредсказуемо тормозить во время игры.
У него всего один метод - getGraphicModel(gameModel).
И суть проще некуда. У gameModel есть хэш-код, а также позиция в игровом мире.
Когда ты подгружаешь graphicModel, ты можешь запихивать их в любой Map или Set.
И так же удалять по хэшкоду или по ключу, который и есть хэшкод.
Но нужен еще один метод, который будет определять, какие объекты нужно подгрузить
на основе положения камер. И это повод для раздумий.
А вот удаление сделать проще некуда. Просто сделай помимо Мэпа еще одну коллекцию,
которая будет цепью типа FIFO. Перед добавлением нового объекта, смотри,
что у нее на конце. Если там не null, удаляй этот объект из Мэпа.
Ты можешь держать под контролем количество подгруженных объектов и расход памяти,
регулируя длину цепочки.
И так, когда нужен объект, просто возьми из кэша,
затем обнови его состояние (трава - переключить колыхание,
персонаж - изменить позу и т.п.).
Не мне тебе говорить, что подгрузка моделей с диска
и прочая поебень должна идти асинхронно.
Если зассал, подгружай объект синхронно, когда его нет в кэше.
Если уверен в своих силах, просто напиши охуенный алгоритм предсказания
попадания в камеру и будет тебе счастье.
-------------
Теперь подумай, что ты получаешь.
У тебя гр. модели сами по себе. Ты можешь на основе тех же классов сделать
рендер для какой угодно поеботни. Более того, ты можешь наоборот,
взять LuxRay или другой готовый рендер, и играть через него realtime с fps=0.5,
где ничего не видно. Просто потому что.
Т.е. рендер не обязан быть один. Когда я говорю про 1 и 2 - это
в первую очередь у них должен быть API, и только потом в отдельных модулях
пробная реализация.
Типа такие модули получаются.
game-api
graphics-api
game-simple-impl
graphics-simple-impl
graphics-luxray-impl
moya-super-gama // здесь Main
moy-render-dlya-kakogo-ta-govna // другая прога, другой Main
Это pros. Cons - то, что если мало памяти или тупанешь,
получится графон, как в Rage.
вещает ОП-хуй
Еще один Cons - то, что в модуле 3 может потенциально возникнуть игромедный if-elsif-elsif-elsif...
Надо этого по возможности избежать.
Должно быть мало разновидностей игровых объектов, и они все должны быть обозначены, как интерфейсы в API.
И еще раз уточню, на всякий случай.
Игровой объект.
Если на уровне сейчас 20 одинаковых зомби, у нас 20 объектов.
Графический объект.
Если на уровне сейчас 20 одинаковых зомби, нужен 1 объект.
Тут я немного сплоховал по части мэпов,
хэшкодов и прочей поеботни, но если использовать как хэш
не id объекта, а id класса, всё возвращается на круги своя.
Главное не забывать переключать состояния граф объектов перед
отрисовкой.
>>350398
Обращайся. Если клепаешь опенсорц - скидывай ссылку обязательно.
Индивидуализм иногда ни к чему.
бмап наперегонки
Задавай практические жопские и странные вопросы и задачи по ООП. Буду заглядывать сюда раз в три дня и отвечать.