(ссылки на игровые площадки к решениям с использованием параметров типа и связанных типов )
В этом случае &T
и &mut T
являются двумя разными типы. Код, который является общим для разных типов (как во время компиляции, так и во время выполнения), идиоматически написан в Rust, используя черты. Например, учитывая:
struct Foo { value: i32 }
struct Bar { foo: Foo }
, предположим, что мы хотим предоставить Bar
общий аксессор для своего члена данных Foo
. Аксессор должен работать как с &Bar
, так и с &mut Bar
, соответствующим образом возвращающим &Foo
или &mut Foo
. Таким образом, мы пишем черту FooGetter
trait FooGetter {
type Output;
fn get(self) -> Self::Output;
}
, задача которой должна быть общей для конкретного типа Bar
. Его тип Output
будет зависеть от Bar
, так как мы хотим get
иногда возвращать &Foo
, а иногда &mut Foo
. Обратите также внимание на то, что он потребляет self
типа Self
. Поскольку мы хотим, чтобы get
был общим для &Bar
и &mut Bar
, нам нужно реализовать FooGetter
для обоих, так что Self
имеет соответствующие типы:
// FooGetter::Self == &Bar
impl<'a> FooGetter for &'a Bar {
type Output = &'a Foo;
fn get(self) -> Self::Output { & self.foo }
}
// FooGetter::Self == &mut Bar
impl<'a> FooGetter for &'a mut Bar {
type Output = &'a mut Foo;
fn get(mut self) -> Self::Output { &mut self.foo }
}
Теперь мы можем легко используйте .get()
в общем коде, чтобы получить &
или &mut
ссылки на Foo
из &Bar
или &mut Bar
(просто требуя T: FooGetter
). Например:
// exemplary generic function:
fn foo(t: T) -> ::Output {
t.get()
}
fn main() {
let x = Bar { foo: Foo {value: 2} };
let mut y = Bar { foo: Foo {value: 2} };
foo(&mut y).value = 3;
println!("{} {}\n", foo(&x).value, foo(&mut y).value);
}
Обратите внимание, что вы также можете реализовать FooGetter
для Bar
, так что get
является общим для &T
, &mut T
и T
(по перемещая его). Это на самом деле способ, которым метод .iter()
реализован в стандартной библиотеке и почему он всегда делает «правильную вещь» независимо от ссылочного аргумента, на который он ссылается.
Убедитесь, что вы добавили следующее разрешение в свой манифест
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
А также вместо непосредственного добавления относительного макета, разведите представление из xml, содержащее относительный макет, подобный этому
overlayView = LayoutInflater.from(this).inflate(R.layout.overlay_layout, null);