Страницы

Поиск по вопросам

понедельник, 8 апреля 2019 г.

Как удалить из локального коммита изменение в виде удаления папки с файлами?

Есть коммит состоящий из изменений пары файлов и удаления папки (не пустой). Сейчас мне нужно изменить этот коммит перед push так, чтобы та папка все же осталась, изменения коснулись только кода
Я пробую
git rm --cached foldername git rm -r --cached foldername
но получаю did not match any files
Как можно исправить ситуацию?


Ответ

Можно просто вытащить эту папку обратно из предыдущего коммита:
git checkout HEAD^ -- foldername
Она будет уже в индексе, вам останется только заменить коммит-верхушку новым, в котором эта папка есть:
git commit --amend

Стандартное предупреждение для читателей: --amend переписывает историю, не используйте на коммитах, которые уже публиковали в общие ветки. Вопрос этого и требует, просто подчёркиваю лишний раз, пока кому-нибудь не пришлось с грустным лицом искать свои коммиты в рефлоге

Диапазон символов в регулярном выражении

Какие символы включает регулярное выражение [а-яА-Я]+? Известно, что оно не включает символы ё и ъ. И для того, чтобы охватить весь алфавит русского языка нужно писать [а-яА-ЯёЁъЪ]+ ? Или есть какие-то ещё символы алфавита русского языка, которое это выражение не включает? Как узнать весь диапазон включённых в регулярное выражение символов?


Ответ

Регулярные выражения Java поддерживают стандарт регулярных выражений для Юникода (Unicode® Technical Standard #18 UNICODE REGULAR EXPRESSIONS). Соответственно, диапазоны символов считаются по кодовым позициям в Юникоде.
Буквы русского алфавита занимают в Юникоде позиции с 0410 по 044F, кроме букв «ё» и «Ё», которые по историческим причинам поставлены на позиции не соответствующие русскому алфавиту (найдите их в таблице символов). Это и вызывает необходимость указывать их отдельно.
Есть какие-то ещё символы алфавита русского языка, которое это выражение не включает
Нет, даже для твердого знака не нужно делать исключения.
Как узнать весь диапазон включённых в регулярное выражение символов?
По кодовым позициям. В Java числовое значение символа (char) соответствует его позиции в Юникоде. Соответственно, можно задать переменные char для границ диапазона и пройтись циклом по всем символам. Например, следующий код выводит все символы, входящие в диапазон от «А» до «Я» и их позиции в Юникоде.
for(char ch = 'А'; ch<='Я'; ch++) { System.out.println(ch +" ("+ ((int) ch)+")"); }

Совпадение в пределах диапазона

Есть база данных Teams. Состоящая из country, capital и teamName. Нужно отобразить те страны в порядке убывания, у которых в названиях столиц ровно две буквы в диапазоне от "а" до "д".
Проверку на вхождение букв из диапазона понятно как сделать, а вот как узнать что этих букв именно 2?
SELECT country, capital FROM Teams WHERE capital like '%[а-д]%' ORDER BY country DESC


Ответ

С точностью до диалекта SQL:
SELECT country, capital FROM Teams WHERE capital LIKE '%[а-д]%[а-д]%' AND capital NOT LIKE '%[а-д]%[а-д]%[а-д]%' ORDER BY country DESC

Рефлексия. Как вызвать метод с ref generic параметрами?

Имеем такой класс и метод
public class TestClass { public void Swap(ref T first, ref T second) { T tmp = second; second = first; first = tmp; } }
Пытаюсь задействовать рефлексию и вызвать метод
[TestMethod] public void InvokeGenericMethod() { MethodInfo method = typeof(TestClass).GetMethod("Swap"); MethodInfo methodWithInt = method.MakeGenericMethod(typeof(int));
int one = 1; int two = 2; object[] arguments = { one, two }; methodWithInt.Invoke(this, arguments);//здесь ошибка
Assert.AreEqual(one, 2); }
и получаю ошибку {"Объект не соответствует конечному типу."}
Как это делается? Гуглеж приводил к примерам с одним параметром out и чего-то все вызывалось как обычно, т.е. массив аргументов создавался как у меня, а далее обычный вызов через Invoke(). Какие идеи?


Ответ

Вы вызываете нестатический метод, и должны передать в качестве первого аргумента Invoke объект, у которого вы этот метод хотите вызвать. И это должен быть объект того класса, метод которого вы вызываете:
methodWithInt.Invoke(new TestClass(), arguments);
Или вы можете поменять метод на статический, и передавать null в качестве первого аргумента:
public class TestClass { public static void Swap(ref T first, ref T second) { T tmp = second; second = first; first = tmp; } }

methodWithInt.Invoke(null, arguments);
Кстати, в MSDN по Invoke подробно расписано, в каких случаях он бросает TargetException. Стандартная документация значительно облегчает поиск причины ошибки :)

Одному фрагменту один презентер?

Есть активити у которого 3-4 фрагмента .Для каждого из низ надо создать View и Presenter?или Несколько View можно привязать к одному презентеру?


Ответ

Ответ может быть дан только тогда, когда вы сами архитектурно примите решение, я постараюсь помочь:
Согласно MVP по структуре у вас у каждой view должен быть свой pesenter, логично. В нашем случае нужно просто решить что такое View, если к примеру у вас activity, то фрагменты в таком случае часто называют subView, и они будут являться дополнением основной View кое у вас Activity, тогда у них будет общий presenter. На самом деле в небольших проектах я бы делал именно так, будет меньше зависимостей, генерируемого кода, интерфейсов, и легче будет построить логику между фрагментами, хотя такую зависимость лучше избегать, но... Presenter этой view (activity) разрастеться, и потом будет тяжело расщеплять эти куски, также такая паутина будет тяжелее тестироваться, ну опять же если проект большой. Чтоб убедить, что такой подход довольно частый, гугл его предлагает во время аттестации и описывает в stable blue prints MVP.
Другой очевидный вариант, что activity выступает в роли View, а каждый фрагмент это тоже View, что тоже вполне логично, тогда нужно будет делать для них отдельные presenter. Те будет View(Activity) -> Presenter, View(Fragment) -> Presenter. Плюсы будут в том что такие фрагменты будут полностью независимы, и у нас не будет такого God object в роли жирного Presenter с логикой всех фрагментов внутри. Такой код легче будет поддерживать и тестировать, фрагменты можно использовать правильно по их назначению в других местах приложениях, как угодно при этом придется поправить только поведение, те в Java эту роль берет интерфейс. Проблема есть только в начальной структуре, например в Dagger2 чтоб выстроить такой граф нужно время и умение. Те по сути вы жертвуете начальным временем, чтоб решить какое будет поведение и всё. Такой подход я считаю более правильным, но его почему-то реже видно в исходниках или примерах в сети.

Перегрузка оператора сложения для дробей

Пишу класс рациональных чисел. Хочу перегрузить оператор сложения, чтобы можно было складывать с дробями целые числа. Всё получилось, но проблема в том что возможна запись <мой класс> = <мой класс> + <целое число> Если же я пишу так: <мой класс> = <целое число> + <мой класс> всё крашится: no match for 'operator+' (operand types are 'int' and 'Number')
Вoт код в .h:
class Number { public: Number(int numerator = 0, int denominator = 1);
int getNumerator() {return this->numerator;} int getDenominator() {return this->denominator;} string toString();
// определяем арифметические действия дробей с дробями Number operator+ (Number &other); Number operator- (Number &other); Number operator* (Number &other); Number operator/ (Number &other);
// определяем арифметические действия дробей с целыми числами Number operator+ (int i); protected: int numerator; // числитель int denominator; // знаменатель };
Код в .cpp:
Number Number::operator+(int i) { Number res(i * this->denominator() + this->numerator(), this->denominator()); return res; }


Ответ

Вот в том числе и по этой причине такие операторы рекомендуется реализовывать не методами класса, как у вас, а отдельными (дружественными) функциями. Вы реализовали именно оператор сложения, в котором целое является правым операндом. Реализовать оператор сложения для целого числа в качестве левого операнда методом класса невозможно в принципе. Его в любом случае придется реализовывать обычной функцией.
Но тут на самом деле стоит сделать шаг назад и посмотреть на общий дизайн. Вам на самом деле вообще не нужно реализовывать операторы для сложения с целыми числами. Ваш класс Number уже обладает конвертирующим конструктором, который умеет преобразовывать целые числа в ваш Number. После этого ваши готовые операторы для операндов типа Number уже сами сделают все правильно. Для этого, однако необходимо 1) реализовать их обычными функциями, 2) не забыть о const в параметрах-ссылках, который у вас почему-то отсутствует.
class Number { public: Number(int numerator = 0, int denominator = 1);
// определяем арифметические действия дробей с дробями friend Number operator +(const Number &lhs, const Number &rhs); friend Number operator -(const Number &lhs, const Number &rhs); friend Number operator *(const Number &lhs, const Number &rhs); friend Number operator /(const Number &lhs, const Number &rhs);
protected: // <- ??? int numerator; // числитель int denominator; // знаменатель };
Такой класс уже сам по себе будет поддерживать
Number a(2, 3); Number b = a + 1; Number c = 25 + a;
и ничего для этого дополнительно писать не надо.
Если вам при этом захочется написать отдельные реализации для операций с обычными числами (например, в целях оптимизации) - вы можете это сделать. Но лучше это делать обычными функциями с двумя параметрами, как показано выше, а не методами класса.

Селект в коллекцию с пользовательским типом данных

Как сделать селект в в коллекцию с пользовательским типом данных?
Например, есть таблица:
create table emp ( empno number(4,0), ename varchar2(10), job varchar2(9), mgr number(4,0), hiredate date, sal number(7,2), comm number(7,2), deptno number(2,0), constraint pk_emp primary key (empno), constraint fk_deptno foreign key (deptno) references dept (deptno) )
Cоздаю пользовательский тип:
CREATE OR REPLACE TYPE typ_emp as OBJECT ( name VARCHAR2(20), deptno VARCHAR2(20) );
CREATE OR REPLACE TYPE emp_tbl AS TABLE OF typ_emp;
Пишу функцию:
CREATE OR REPLACE FUNCTION getEmpl RETURN emp_tbl AS tbl emp_tbl ; BEGIN SELECT e.ENAME, e.DEPTNO INTO tbl FROM EMP e; RETURN tbl; END;
Компиляция с ошибками:
PL/SQL: ORA-00947: not enough values PL/SQL: SQL Statement ignored


Ответ

Вам надо обернуть результат запроса в нужный тип и извлекать через bulk collect into
CREATE OR REPLACE FUNCTION getEmpl RETURN emp_tbl AS tbl emp_tbl ; BEGIN SELECT typ_emp(e.ENAME, e.DEPTNO) BULK COLLECT INTO tbl FROM EMP e; END;
Чуть больше примеров на en-so
И сейчас ваша функция не возвращает никакого результат, это странно.