том, что X приватный. Как это можно обойти?
Сделать X публичным. Как это не странно. Ну по крайней мере как я понял с твоего абстрактного описания (лучше б 10 строчек кода на плейграунде б сделал). Он используется в публичном интерфейсе, значит должен быть публичным. То что ты в явном виде сейчас не видишь Х, не означает, что Х не нужен компилятору. И метод foo.bar() из A<X> ,будет развернут в что-то типа <Foo as A<X>>::bar(& foo).
Да, я в конечном итоге так и сделал. Проблема в том, что у x нет публичных методов, полей и конструктора. Его нельзя ни откуда публично получить. Это так специально сделано, и по уму и сам тип тогда должен быть приватным, но в результате он будет публичный в крейте, и непонятно зачем
Даже если его нет на уровне объектов у пользователя, ты зачем-то его используешь на уровне типов. А значит всё-таки он нужен. Например в случае конфликтов имён методов, пользователю явно нужно будет указать откуда этот метод. Тогда он этот Х точно затребует.
Вообще, я этот "паттерн"(с трейтами A и B, который я описал) использовал для того, чтобы обобщить повторяющуюся часть имплементации нескольких частично схожих объектов в своем крейте. При этом B мне фактически нужен только для того, чтобы получать приватную информацию об объекте(собственно это и есть тот самый X), а A делает фактическую имплементацию через дефолтную имплементацию собственных трейтных методов. Может быть это можно было сделать как-то проще?
1. Ну скорее всего у тебя тут Х не тайп параметр, а ассоциативный тип должен быть. 2. trait A: B, боунд наверное тоже не обязателен, так как B у тебя просто "детали реализации". 3. Ну и вообще трейт B, имхо, это попытка натянуть ООП, на Раст, по хорошему Трейт должен описывать поведение, а не реализовывать доступ к полям. Как это можно написать учитывая 1-2: trait B { type X; fn inner(&mut self) -> &mut Self::A } impl B for S<T>{type X = T;...} ... trait A{ fn reset(&mut self); } impl<X> A for X where X: B, <X as B>::X : Default, { fn reset(&mut self) ->{* self.inner = Default::default()} }
@c_vld Как вы предложили, сделать к сожалению не получилось. Я сделал B как pub(crate)(в противном случае inner() был бы публично доступен, что противоречит самой цели), и он тогда ругается, что "crate-visible trait B in public interface" на impl<X> A for X where X: B, <X as B>::X : Default,
Кто мешает засилить трейт, чтобы другие крейты не могли имплементить трейт?
сленг растовый, конечно, стремный
Так и что мне это даст? Если я impl в приватный модуль запихаю, у меня этого имлпа не будет в публичном интерфейса крейта
Не, пихаешь ты его в pub, но он зависит от private Sealed трейта, так что только ты можешь его имплементить.
А, ну ок, так заработало. Но все равно X получается должен быть публичным
В смысле, то что inner возвращает
А какая разница, если только ты терйт можешь имплементить?
Ну, это не критично, но некоторый недостаток. Я буду вынужден типы для Inner делать публичными, оставляя при этом все что можно у них приватным(конструктор, акцессоры и т.п.). Он по уму бы тогда и сам должен был бы быть приватным. Это некая характеристика, которую хотелось бы получить в конечном итоге
Ну, что сказать. Не ты один хотел бы.
Обсуждают сегодня