Как мне вызвать геттер из другого модуля субстрата? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть два модуля, MyCore и Special. MyCore имеет Publi c getter:

pub fn get_core_account() -> Option<T::AccountId>

, который получает accountId. Если я вызываю это из Special простым способом:

let core_account = MyCore::get_core_account();

, тогда rust c жалуется, что не может вывести тип, что странно, потому что установщикам publi c больше не нужно Информация. Поэтому я делаю тип явным

let core_account: Option<T::AccountId> = MyCore::get_core_account();

Но это вызывает требования к спецификаторам типов при вызове, поэтому мы уточняем:

let core_account: Option<T::AccountId> = MyCore::<T>::get_core_account();

В этот момент Руст жалуется, что не может найти get_core_account, потому что Special не имеет ограничений для реализации MyCore::Trait. Но я не хочу, чтобы Special реализовал MyCore::Trait! Я хочу вызвать геттер!

Возможно, я что-то упускаю из-за использования T здесь - теоретически Special - это черта, заданная для некоторого T, которую мы можем реализовать с помощью класса Test, если мы реализуем необходимые типы.

Действительно ли Special нужно реализовать MyCore::Trait?

1 Ответ

0 голосов
/ 09 апреля 2020

То, что вы хотите сделать, возможно, но вы, вероятно, делаете что-то не так, что неясно продемонстрировано в вопросе. Было бы очень полезно, если вы опубликуете Trait определения обоих модулей.


Действительно ли Special необходимо реализовать MyCore :: Trait?

Нет. Возможно, вам придется ограничить эту черту.

По сути, у вас есть два варианта в таких случаях:

  1. Если ваш Core - это то, от чего будут зависеть все другие модули Подобно frame-system, вы можете явно зависеть от него. Обратите внимание, что этот путь следует использовать с осторожностью, и вы не хотите создавать слишком большое программное обеспечение monolithi c с таким мышлением. Тем не менее, в этом случае вы можете просто сделать:
// in special.rs
// This is needed because then we can pass `T` into `mycore::Module<_>`.
pub trait Trait: mucore::Trait {
   ...
}

// and then later on you can call:
<mycore::Module<T>>:: get_core_account()

Это похоже на подход, который вы хотели использовать.

Кроме того, вы можете связать два модуля вместе без этой явной зависимости. Это полезно, когда вы хотите, чтобы ваш Special в конечном итоге получил получатель, но вам все равно, кто его предоставляет. Или, другими словами, если несколько кандидатов могут предоставить этот метод получения, и вы хотите быть обобщенным c над ним.

Для этого вам сначала нужно общее определение черты.

// in some common dependency
trait CoreGetterProvider<AccountId> {
  fn getter() -> Option<AccountId>;
}

и ваш Special будет express:

pub trait Trait {
  // .. other stuff. Assuming that it has a common AccountId with Core. 
  type Getter: CoreGetterProvider<Self::AccountId>
}

И ваш Core реализует его

// in Core.rs
impl<T: Trait> CoreGetterProvider<T::AccountId> for Module<T> { ... }

Наконец, при построении среды выполнения Вы можете передать модуль Core на Special.

impl core::Trait for Runtime { ... }
impl special::Trait for Runtime {
  type Getter = core::Module<Runtime> // or just `Core`. construct_runtime! creates this type alias. 
}
...