RUST에서 서로 다른 유형의 여러 개체를 보유하기 위한 이기종 유형 생성
Vec<T>; // an vector
[T;N]; // an array
(); // tuple
필요한 다양한 시나리오에 따라 사용할 수 있는
이기종 유형으로 사용할 수 있지만 컴파일 시간 동안 적용되는
Sized
특성에 의해 자연스럽게 제한되어 동적으로 추가로 사용하도록 제한됩니다.여기서 주목해야 할 핵심 사항은 유형에서 도출할 수 있는 공통 관계를 기반으로 유형을 분리할 수 있다는 것입니다.
그러나 Rust에서 이기종 유형을 지원하는 경우 포인터 뒤에 있는 vtable의 개체를 가리키는
dyn
특성을 사용하여 사용 가능한 여러 유형의 개체를 수용할 수 있는 유형을 구성하는 것이 약간 까다로워집니다.당신은 읽을 수 있습니다 here ,
런타임 중에 유형의 크기를 조정할 수 있기를 원하므로 개체를 저장할 수 있는
Vec<T>
유형을 선택하겠습니다.이 특성을 적용하는 유형이 두 가지 기술을 사용하여 개체를 직접 참조할 수 있기 때문입니다.
1) 객체에 대한 참조 사용
Vec<&dyn yourTrait>;
2) Box 스마트 포인터 뒤에 개체 배치
Vec<Box<dyn youTrait>>;
특성의 이름이
Foo
이고 구현될 하나의 메서드를 선언한다고 가정해 보겠습니다.trait Foo {
fn call(&self);
}
이제 우리는 이것을 구현할 임의의 유형을 만들 것입니다.
다음과 같다
(단순화를 위해 여기서는 튜플 구조체를 정의했지만 유형은 이것보다 훨씬 더 복잡할 수 있습니다 ... 특성을 구현하는 한 괜찮을 것입니다)
#[derive(Debug)]
struct A(i32);
impl Foo for A {
fn call(&self) {
println!("type A: {:?}", self.0);
}
}
#[derive(Debug)]
struct B(i32);
impl Foo for B {
fn call(&self) {
println!("type B: {:?}", self.0);
}
}
#[derive(Debug)]
struct C(i32);
impl Foo for C {
fn call(&self) {
println!("type C: {:?}", self.0);
}
}
여기에서 모든 유형이 특성 메소드의 동일한 정확한 정의를 구현하지만 해당 유형으로 수행하려는 작업에 따라 다를 수 있다는 이상한 점을 관찰할 수 있습니다.
이제 간단하게 저장할 수 있는 유형 선언을 시작하겠습니다.
첫 번째 방법에 따라
*1) 객체에 대한 직접 참조 사용 *
여기서 주목해야 할 한 가지 중요한 점은 유형에 제공할 참조가 변경 가능하거나 변경 불가능하다는 것입니다!
즉, 모든 특성 객체에 균일하게 적용되며 일부 특성 객체는 가변적으로 전달되고 다른 특성 객체는 불변으로 전달될 수 없습니다.
fn main() {
//some random trait objects declared
let a = &A(43);
let b = &B(73);
let c = &C(95);
// now we will compose our homogenous type based on the previously types
let objs: Vec<&dyn Foo> = vec![a, b, c];
for I in objs.iter() {
I.call();
}
}
객체
a, b, c
가 각각 유형A, B, C
에 대한 참조를 보유하고 있으므로 여기에서 직접 전달하여 동종 유형을 구성할 수 있습니다.출력 :
type A: 43
type B: 73
type C: 95
2) Box 스마트 포인터 사용하기
이제 우리는 또 다른 흥미로운 방법을 시도할 것입니다. 이 경우 객체를 Box 스마트 포인터 뒤에 배치합니다. 이 경우 컴파일 자체 중에 특성 객체를 초기화하는 것에 대해 걱정할 필요가 없습니다. 대신 포인터 포인팅 뒤에 배치합니다. 힙의 메모리 위치로
이 기술에서는 차용 규칙이 적용되지 않기 때문에 함께 작업하는 것이 상당히 설득력이 있습니다.
또한 플러스 측면은 객체가 초기화될 수 있다는 것입니다. 추가적인 이점인 런타임 동안
fn main() {
//here we place our objects behind a box pointer
let a = Box::new(A(43));
let b = Box::new(B(73));
let c = Box::new(C(95));
//our type hold a boxed trait object as type to accept
let mut objs: Vec<Box<dyn Foo>> = vec![a,b,c] ;
for I in objs.iter() {
I.call();
}
}
여기서 출력은 이전 출력과 정확히 동일하지만 상자 포인터의 더 많은 기능이 있습니다.
type A: 43
type B: 73
type C: 95
거기 당신은 .. 새로운 유형을 만드는 방법을 성공적으로 배운 것을 축하합니다 >>
😊 여기까지 읽어주셔서 감사합니다 🥂🎉🎊!
의견, 제안, 의심 또는 조언이 있는 경우 의견 섹션에 자유롭게 게시하십시오.
Reference
이 문제에 관하여(RUST에서 서로 다른 유형의 여러 개체를 보유하기 위한 이기종 유형 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/artechgit/creating-a-heterogenous-type-for-holding-several-objects-of-different-types-in-rust-242c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)