Trait UniformObjectDeref
pub trait UniformObjectDeref<Declarer>: GodotClass {
type TargetRef<'a>: Deref<Target = Self>;
type TargetMut<'a>: DerefMut<Target = Self>;
// Required methods
fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a>;
fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a>;
}
Expand description
Unifies dereferencing of user and engine classes, as &T
/&mut T
and Gd<T>
.
This is mainly used by the connect_*
functions of TypedSignal
.
§Motivation
Although both user and engine classes are often wrapped in a Gd<T>
, dereferencing them is done differently depending
on whether they are made by the user or engine:
Gd<EngineClass>
can be deref-ed directly into&EngineClass
and&mut EngineClass
.Gd<UserClass>
must first go throughbind()
/bind_mut()
, which can finally be deref-ed into&UserClass
and&mut UserClass
, respectively.
Without this trait, there’s no clear/generic way of writing functions that can accept both user and engine classes, but need to deref said classes in some way.
UniformObjectDeref
solves this by explicitly handling each category in a different way, but still resulting
in a variable that can be deref-ed into &T
/&mut T
.
§Generic param Declarer
Rustc does not acknowledge associated type bounds when checking for overlapping impls, this parameter is essentially used to create 2 different traits, one for each “category” (user or engine).
Despite being 2 different traits, a function can accept both by simply being generic over Declarer
:
use godot::meta::UniformObjectDeref;
fn abstract_over_objects<Declarer, C>(obj: &Gd<C>)
where
C: UniformObjectDeref<Declarer>,
{
let ref_provider = UniformObjectDeref::object_as_ref(obj);
let obj_ref: &C = & *ref_provider;
// Regardless of `Declarer`, we can still deref, since the bounds on
// `TargetRef`/`TargetMut` enforce that.
}
#[derive(GodotClass)]
#[class(init)]
struct MyClass {
_base: Base<RefCounted>
}
fn main() {
let engine_obj: Gd<RefCounted> = RefCounted::new_gd();
let user_obj: Gd<MyClass> = MyClass::new_gd();
abstract_over_objects(&engine_obj);
abstract_over_objects(&user_obj);
}
Required Associated Types§
Required Methods§
fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a>
fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.