Pull to refresh
6
0

Небесный механик

Send message

Гн вижу ничего плохого в том чтобы похвалить хорошую статью, как. впрочем и покритиковать, если есть за что.

Если вы не заметили, статья называется “C# делегаты изнутри…”, это вроде как главное, если, конечно, вы мне разрешите, что-то решить по поводу моей статьи. Ну ладно, замнем для ясности.

Хм, перечитал по новой и, совсем ничего не нашел про то, как делегат в C# устроен изнутри, т.е. как делегат выглядит на уровне CIL и что происходит в CLR\Mono когда оно выполняетт соответсвующие инструкции. Да и весь рассказ про делегаты в C# сводится к предложению: "Там делегаты определяются с помощью ключевого слова delegate".

И да, коль я перечитал еще раз статью, хотелось прокомментировать интересный момент:

Есть еще одна сложность с пониманием делегатов. Мы привыкли что в переменных у нас хранятся данные, а в переменной типа Делегат мы сохраняем функцию, а функция — это блок кода. 

А вы думали почему указатели на функцию и методы в Си++ такие как есть?

Спасибо, мне казалось что добавит ограничения и на сам тип. Был не прав. Но в любом случае вы не сможете сделать let a: &dyn TraitA = &A{};

Unsafe Rust куда "опаснее" в этом смысле, чем C или C++.

Соглашусь со всем комменатрием кроме этого предложения. UB в С++, как и в Unsafe Rust контринтутивен и хрен редьки не слаще.

Мешает то, что тип А реализует TraitA. Этой ситуации не может быть в принципе при наследовании.

И? Чем плоха возможность делать impl dyn Trait?

Да ничем, более того это единственный вариант, когда можно реализовать кастование dyn объектов пока не завезли в стабильную ветку. Но то, что в ООП называется интерфейсами в Расте возможно только через dyn объекты, а их не для каждого типажа можно создать.

trait TraitA{
  fn a(); // колючевое слово self отсутствует
}
trait TraitB: TraitA{
 fn b(&self);
}

trait TraitC {
 fn c (&self);
}

struct A{
}

impl TraitA for A{}

impl TraitB for A{}

impl TraitC for A{}

struct B{
}

impl TraitC for B {}

Вот в такой конструкции вы не сможете создать dyn TraitA, а из-за это не может создать dyn TraitB, также мы не можем создать dyn TraitC для типа А, но можем для типа B.

Значит уже затащили в стабильную ветку, где-то еще год назад такой фокус не проходил. Запаривало страшно.

Нет, при реализации трейта вы не можете использовать методы из реализации соседнего трейта, только методы и данные самого типа. Т.е. если учть продолжить пример у вас будет:

trait TraitA{
  fn a(&self);
}
trait TraitB: TraitA{
 fn b(&self);
}

struct My
{
  d: i32,
}
impl My
{
  fn a_p(&self) {
  }
}

impl TraitA for My{
  fn a(&self){
    self.a_p());
  }
}

impl TraitB for My{
  fn b(&self){
    self.a_p()); 
    // и только так, вы не можете сделать self.a()
  }
}

Ключевое слово dyn достаточно хитрое. По факту оно создает новый тип "dyn Trait", который содержит указатель на данные и указатель на методы. Но, помимоо этого вы можете сделать:

impl dyn Trait
{
  pub fn my_fn(&self) {
  }
}

У типажей нету механизма наследования когда вы пишите:

trait TraitA{}

trait TraitB: TraitA{}

Вы не наследуете TraitB от TraitA, вы накладывает ограничения, чтобы тип определяющий TraitB также определял бы и TraitA. И это две большие разницы.

Нет, они что-то сродни концептам.

Это не совсем корректный вопрос. Да, некоторые из тех проверок которые в Си++ проходится делать в рантайме, в Расте можно делать на этапе компиляции. Но вот в чем прикол: понятие "объект" у вас при этом исчезает. И если во многих случаях без него можно обойтись не потеряв производительности (хотя придется и поломать голову), то в некоторых областях (тот же пользовательский интерфейс) это доставлет массу проблем, которые, вполне возможно, выливаются в потерю производительсноти.

Мысль такая: "Если перевыпуск Visa и MasterCard был свзяан с безопасностью, то в условиях когда они не перевыпускаются, то м.б. это и оправдано". Однако видите здесь сколько "м.б." и "если"? Вот отсюда и вопрос

Интересно, а с чем был связан постоянный перевыпуск карт этих систем?

В твердых телах распространение звука имеет принципиально иной механизм, чем в газе. В газе больше роль имеет средняя скорость частиц, которая зависит от массы молекулы и температуры.

Молекулы и атом целиком уже классический объект.

Мой опыт показывает, что в 999 случаев из 1000 необходимость в тестировании внутренних методов класса говорит о неправильной декомпозиции. В очень редких случаях, это действительно нужно, но эти тесты уже что-то среднее между интеграционными и юнит-тестами.

По идее могу, аксиома выбора мне это позволяет..

UPD Протупил.

Information

Rating
5,349-th
Location
Монино, Москва и Московская обл., Россия
Registered
Activity