Национально-правовой механизм
В него входит совокупность внутригосударственных средств, которые призваны обеспечивать реализацию норм МП. К ним относятся:
- Система органов, принимающих участие в имплементации международных норм. Например, Министерство юстиции РФ – центральный орган РФ, который в соответствии с Указом Президента от 2004 года несет ответственность в вопросе обеспечения реализации норм Конвенции ООН, направленной против транснациональной оргпреступности, от 2000 года.
- Свод установлений национального права, которые обеспечивают эффективность осуществления норм МП внутри страны. Например, закон от 2006 года № 40-ФЗ, регулирующий процесс ратификации и имплементации Конвенции ООН по противодействию коррупции.
Пример 4: std::popcount()
, как и , в C++20 предлагается добавить в . И это, разумеется, чудовищно плохое название. Если не знать, что эта функция делает, догадаться невозможно. Мало того, что сокращение сбивает с толку (pop в названии есть, но pop/push тут ни при чём) — расшифровка population count (подсчёт населения? число популяций?) тоже не помогает.
С другой стороны, идеально подходит для этой функции, потому что она вызывает ассемблерную инструкцию popcount. Это не то что название имплементации — это полное её описание.
Тем не менее, в данном случае разрыв между разработчиками языка и программистами не так уж и велик. Инструкция, считающая количество единиц в двоичном слове, называется popcount с шестидесятых. Для человека, хоть сколько-нибудь разбирающегося в операциях с битами, такое название абсолютно очевидно.
Кстати, хороший вопрос: придумывать ли названия, удобные для новичков, или оставить привычные для олдфагов?
Три способа
Понять, что значит «имплементация», поможет изучение способов ее осуществления.
К таким способам относят:
- Инкорпорацию.
- Трансформацию.
- Отсылки: общую, частную, конкретную.
Рассмотрим их:
- В результате применения способа инкорпорации международные нормы воспроизводятся дословно, без всяких изменений в законодательство государства, которое их имплементирует.
- В случае трансформации при внедрении международных норм, прописанных в договоре, в национальное законодательство осуществляется некоторая их переработка. Как правило, это практикуется, когда есть необходимость учитывать национальные стандарты юридической техники и правовые традиции.
- Когда используют отсылки, подразумевается, что содержание международных норм не включается в сам текст закона. В нем лишь содержится указание на них. Тем самым предполагается, что применение национальных правовых норм невозможно без обращения к первоисточнику, то есть к тексту международного документа.
Осуществление норм, установленных международным правом, обеспечивается с помощью различных правовых механизмов. Среди них присутствует различие международно- и национально-правового механизмов внедрения норм. Для того чтобы в полной мере усвоить значение слова «имплементация», рассмотрим их.
Пример 2: std::bless()
Сейчас будет не про названия
Небольшое отступление: в С++ арифметика указателей работает только с указателями на элементы массива. Что, в принципе, логично: в общем случае набор соседних объектов неизвестен и “в десяти байтах справа от переменной ” может оказаться что угодно. Это однозначно неопределённое поведение.
Но такое ограничение объявляет неопределённым поведением огромное количество существующего кода. Например, вот такую упрощённую имплементацию :
Мы выделили память, перенесли все объекты и теперь пытаемся убедиться, что указатели указывают куда надо. Вот только последние три строчки неопределены, потому что содержат арифметические операции над указателями вне массива!
Разумеется, виноват тут не программист. Проблема в самом стандарте C++, который объявляет неопределённым поведением этот очевидно разумный кусок кода. Поэтому P0593 предлагает исправить стандарт, добавив некоторым функциям (вроде и ) способность создавать массивы по мере необходимости. Все созданные ими указатели будут магическим образом становиться указателями на массивы, и с ними можно будет совершать арифметические операции.
Всё ещё не про названия, потерпите секундочку.
Вот только иногда операции над указателями требуются при работе с памятью, которую не выделяла одна из этих функций. Например, функция по сути своей работает с мёртвой памятью, в которой вообще нет никаких объектов, но всё же должна сложить указатель и размер области. На этот случай P0593 предлагал функцию (там была ещё другая функция, которая тоже называется , но речь не о ней). Она не оказывает никакого эффекта на реально существующий физический компьютер, но создаёт для абстрактной машины объекты, которые разрешили бы использовать арифметику указателей.
Название было временным.
Так вот, название.
В Кёльне перед LEWG поставили задачу — придумать для этой функции название. Были предложены варианты и , потому что именно это функция и делает.
Мне эти варианты не понравились.
Название имплементации и название результата
Ни одно из перечисленных названий не является, строго говоря, неверным: они все прекрасно описывают то, что делает функция. действительно считает двоичный логарифм и прибавляет к нему единицу; имплицитно создаёт объекты, а частично сортирует контейнер и копирует результат. Тем не менее, все эти названия мне не нравятся, потому что они бесполезны.
Ни один программист не сидит и не думает “вот бы мне взять двоичный логарифм, да прибавить бы к нему единицу”. Ему нужно знать, во сколько бит поместится данное значение, и он безуспешно ищет в доках что-нибудь типа . К моменту, когда до пользователя библиотеки доходит, при чём тут вообще двоичный логарифм, он уже написал свою имплементацию (и, скорее всего, пропустил проверку для ноля). Даже если каким-то чудом в коде оказалось , следующий, кто увидит этот код, опять должен понять, что это и зачем оно нужно. У такой проблемы бы не было.
Точно так же никому не надо “имплицитно создавать объекты” или “проводить частичную сортировку копии вектора” — им нужно переиспользовать память или получить 5 наибольших значений в порядке убывания. Что-то типа (что тоже предлагали в качестве названия ) и было бы гораздо понятнее.
Кейт использует термин название имплементации для , но он прекрасно подходит и к двум другим функциям. Имплементацию их названия действительно описывают идеально. Вот только пользователю нужно название результата — то, что он получит, вызвав функцию. До её внутреннего устройства ему нет никакого дела, он просто хочет узнать размер в битах или переиспользовать память.
Называть функцию на основании её спецификации — значит создавать на ровном месте непонимание между разработчиком библиотеки и её пользователем. Всегда нужно помнить, когда и как функция будет использоваться.
Звучит банально, да. Но, судя по , это далеко не всем очевидно. К тому же порой всё не так просто.
Имплементация миксин на плюсах
Advanced: Тема повышенной сложности или важная.
- Paltr
- Постоялец
Доброго времени суток.
Написал удобную имплементацию миксин — решил выложить, может кому поможет. Собственно хедер: Mixines.h (пока без комментариев).
То есть в примере объявлен интерфейс, который надо реализовать. Далее описываются миксины и делается генератор реализаций интерфейса PhysPointImplGenerator. И используя этот генератор мы можем подменить любую часть реализации интерфейса, при этом компилятор сам поймет, какую часть реализации требуется подменить.
В принципе это только один из вариантов использования.
- kas
- Постоялец
- Paltr
- Постоялец
kas Я так понимаю намек на скорость компиляции. Если да — то именно здесь это не должно быть проблемой, т. к. в основном работа предполагается с интерфейсом, а имплементация легко за PIMPL в cpp скрывается.
- Paltr
- Постоялец
В общем, в новой версии не надо регистрировать миксины. но видимо оно никому не интересно. =
- Nomad
- Забанен
Paltr Что это такое хоть, твой миксин?
- Paltr
- Постоялец
Крайне полезная, ИМХО, вещь но на плюсах ее нет.
- Suslik
- Модератор
пример профита в студию. я так и не придумал, где это может понадобиться.
- Paltr
- Постоялец
Suslik Мне оно сейчас надо для реализации Steering Behavior. Самое оно описать все поведение персонажа в пятнадцати строках. А так применение миксинам всегда найдется — не зря они некоторыми хорошими языками нативно поддерживаются =).
- Suslik
- Модератор
Paltr > Самое оно описать все поведение персонажа в пятнадцати строках > поведение персонажа в пятнадцати строках > ПЯТНАДЦАТИ СТРОКАХ
не, ну правда, приведи какой-нибудь пример, интересно же. можешь из своего нативного, что-нибудь из физикоэнергетических проблем
- Paltr
- Постоялец
Suslik > па-бааам! одна строка. Смешно. Я тебе про генерацию реализации интерфейса, ты мне кусок имплементации Steering Behavior. Разумно. Нужен пример — смотри в инете. Если не найдешь, в чем я сомневаюсь, пиши — пример будет.
- doc.
- Постоялец
Suslik Короче, это наследуемый(в случае с C++), в некотором роде, обобщенный функционал. Можно несколько развить пример из Wiki. Допустим есть «примесь» с различными перегруженными операторами >, Объясните пожалста, тогда чем это лучше простого шаблонного наследования: Очевидно, ничем. Т.к. изначально миксинов в C++ нет и оно эмулируется именно им. Однако, теперь ты знаешь(и я тоже ) как правильно называются подобные штуки
Еще касательно применения, цитата из Wiki: «Данный метод в более развёрнутом виде используется в библиотеке «Boost operators».»
- Paltr
- Постоялец
Suslik > Объясните пожалста, тогда чем это лучше простого шаблонного наследования: А теперь запиши реализацию интерфейса И через 10 миксин (класс А). Это уже неудобно. А потом в получившемся классе подмени одну миксину для того чтобы получить класс Б. Если подменишь — от прошлой все равно останутся «куски» (данные, методы). Альтернатива — вновь наследоваться от интерфейса И и снова описывать 10 миксин реализации. При этом у класса А и Б этот набор отличается лишь на одну миксину. Это из очевидного. Мой вариант подобными недостатками не обладает, да и просто намного гибче и удобней.
Ключевое слово extends в Java
Действие ключевого слова в точности совпадает с его переводом, один класс расширяет другой, что является классическим наследованием. Правила видимости полей и методов сохранились: private доступны только в самом классе, protected в самом классе и во всех наследниках, к public методам и полям можно обращаться откуда угодно. Главное отличие от «сишного» наследования в том, что можно расширять только один класс. Я сейчас не буду рассуждать о том, насколько это удобно, скажу только, что со множественным наследованием в C++ постоянно творилась какая-то каша.
Небольшой пример наследования с помощью ключевого слова extends. Напишем класс Door, который будет описывать характеристики двери, мы можем создать объект этого класса и работать с ним, как с «просто дверью». С другой стороны напишем еще два класса: IronDoor и WoodDoor, которые будут расширять класс Door(== наследуются от класса Door), т.е. добавят свои характеристики к базовым.
Интерфейсы в Java и немного о полиморфизме
Интерфейс – это контракт, в рамках которого части программы, зачастую написанные разными людьми, взаимодействуют между собой и со внешними приложениями. Интерфейсы работают со слоями сервисов, безопасности, DAO и т.д. Это позволяет создавать модульные конструкции, в которых для изменения одного элемента не нужно трогать остальные.
Новички часто спрашивают, чем интерфейс отличается от абстрактного класса. Интерфейсы в Java компенсируют отсутствие множественного наследования классов. У класса-потомка может быть только один абстрактный класс-родитель, а вот интерфейсов класс может применять (имплементировать) сколько угодно.
Интерфейс на Java объявляют примерно так же, как и класс:
В имплементирующем интерфейс классе должны быть реализованы все предусмотренные интерфейсом методы, за исключением методов по умолчанию.
Методы по умолчанию впервые появились в Java 8. Их обозначают модификатором default. В нашем примере это метод say_goodbye, реализация которого прописана прямо в интерфейсе. Дефолтные методы изначально готовы к использованию, но при необходимости их можно переопределять в применяющих интерфейс классах.
Интерфейсы и полиморфизм
Пример выше иллюстрирует один из трех основополагающих принципов ООП — полиморфизм. Мы раскрыли одно и то же явление — съедобность — через несколько классов, свойства и методы которых частично отличаются. Представление разных форм одного явления — это и есть полиморфизм. Если нужно, такую систему всегда можно расширить и скорректировать. В нашем случае — добавить новые виды съестного и методы их приготовления.
В Java полиморфизм можно реализовать через:
- наследование — с переопределением параметров и методов базового класса;
- абстрактные классы — шаблоны для раздельной реализации в разных классах;
- интерфейсы — для имплементации классами.
Интерфейс выручает в ситуации, когда при создании переменной мы не знаем, объект какого класса ей будет присвоен.
Реализация интерфейсов классами Java
Допустим, есть интерфейс Edible, которым пользуются классы Fruit, Vegetable, Fish. Экземпляры этих классов можно создавать так:
Хорошим тоном считается давать интерфейсам названия с окончанием -able/-ible — это показывает, что с объектами, имплементирующими интерфейс, можно что-то делать: Edible (можно есть), Moveable (можно двигать), Clickable (реагирует на клик) и т.д.
Обратите внимание на разницу в конструкторах: для фруктов задаём название и сорт, для рыбы – название, район вылова и вес порции в граммах. Но ссылки на оба объекта храним в переменных одного типа – «Съестное»