상세 컨텐츠

본문 제목

17. Rust 구조 (Struct)

Rust를 처음부터 배우세요

by 러스트코리아 2024. 11. 15. 20:44

본문

반응형

배열은 동일한 유형의 요소만 담을 수 있습니다. 어떤 면에서 배열은 동일한 유형의 요소 모음입니다.

하지만 세상은 그렇게 아름답지는 않습니다. 항상 복사하고 복제하는 방식일 것이며 많은 것들이 더 복잡할 때가 많습니다.

예를 들어, 사람을 설명하려면 나이, 이름, 거주지 주소가 있어야 합니다. 이러한 것들을 저장하고 싶다면 배열이 닿을 수 없습니다.

이 문제를 해결하기 위해 언어 개발자들은 사용자가 유형을 맞춤화할 수 있는 또 다른 방법, 즉 구조(struct) 를 생각했습니다 .

구조는 실제로 구조 입니다 . 일상 생활에서 특정 구조를 언급하면 ​​그것이 무엇으로 구성되어 있는지 분석합니다. 예를 들어, 테이블을 분석할 때 테이블에 다리가 4개 있고, 테이블 상판이 있고, 가로 막대가 여러 개 있다고 가정하겠습니다.

구조는 다른 구조를 포함하여 다양한 유형의 데이터 항목의 조합입니다.

17.1 구조 정의

구조의 개념을 가진 거의 모든 언어에서 구조를 정의하는 데 사용되는 키워드는 동일합니다.

구조가 컬렉션, 즉 복합 유형이기 때문입니다. 구조의 모든 요소/필드도 해당 데이터 유형을 명확하게 나타내야 합니다.

구조를 정의하는 구문 형식은 다음과 같습니다.

  1. struct Name_of_structure {
  2. field1:data_type,
  3. field2:data_type,
  4. field3:data_type
  5. }

구조를 정의할 때:

  • 구조체 이름 Name_of_structure 및 요소/필드 이름 fieldN은 일반 변수의 명명 구문을 따릅니다.
  • 구조의 각 요소/필드에는 명시적으로 지정된 데이터 유형이 있어야 합니다. 기본 유형일 수도 있고 다른 구조일 수도 있습니다.

17.1.1 예

다음 코드에서는 이름, 나이, 회사라는 세 가지 요소/필드가 있는 Employee 구조를 정의합니다.

  1. struct Employee {
  2. name:String,
  3. company:String,
  4. age:u32
  5. }

17.2 구조체의 인스턴스 생성(구조 초기화라고도 함)

구조체의 인스턴스를 생성하거나 구조체를 초기화하는 것은 본질적으로 변수를 생성하는 것입니다. 변수를 만들려면 let 키워드를 사용하세요.

구조체의 인스턴스를 생성하는 구문은 실제로 구조체를 정의하는 것과 유사합니다. 하지만 아직 말하기가 좀 복잡합니다. 먼저 구체적인 구문을 살펴보겠습니다.

17.2.1 구조 초기화 구문

  1. let instance_name = Name_of_structure {
  2. field1:value1,
  3. field2:value2,
  4. field3:value3
  5. };

구문에서 알 수 있듯이 구조체 초기화 시 등호 오른쪽은 정의 구문의 요소 유형을 특정 값으로 대체하는 것입니다.

구조 초기화는 실제로 구조의 각 요소에 값을 할당하는 것입니다.

참고: 후행 세미콜론을 잊지 마십시오.

17.2.2 구조 인스턴스 요소에 접근하기 위한 구문

구조 인스턴스의 요소에 액세스하려면 마침표(.)인 요소 접근자를 사용할 수 있습니다.

구체적인 액세스 구문 형식은 다음과 같습니다.

  1. struct_name_instance.field_name

예를 들어 Employee 인스턴스 emp1의 name 요소에 액세스하려는 경우 다음을 사용할 수 있습니다.

  1. emp1.name

17.2.3 예

다음 코드에서는 세 개의 요소가 있는 Employee 구조를 정의한 다음 인스턴스 emp1을 초기화하고 마지막으로 요소 접근자를 통해 emp1의 세 요소에 액세스합니다.

  1. struct Employee {
  2. name:String,
  3. company:String,
  4. age:u32
  5. }
  6.  
  7. fn main() {
  8. let emp1 = Employee {
  9. company:String::from("TutorialsPoint"),
  10. name:String::from("Mohtashim"),
  11. age:50
  12. };
  13. println!("Name is :{} company is {} age is {}",emp1.name,emp1.company,emp1.age);
  14. }

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. Name is :Mohtashim company is TutorialsPoint age is 50

17.3 구조 인스턴스 수정

구조 인스턴스를 수정하면 구조의 개별 요소가 다시 할당됩니다 .

구조체 인스턴스는 let을 사용하여 정의된 변수이기 때문에 기본적으로 수정할 수 없습니다 .

구조 인스턴스를 수정하려면 인스턴스를 생성할 때 mut 키워드를 추가하여 수정 가능하게 만들어야 합니다.

새로 배울 내용은 없으므로 바로 예제로 넘어가겠습니다.

17.3.1 예

다음 예에서는 emp1의 내부 요소를 수정할 수 있도록 Employee 인스턴스 emp1에 mut 키워드를 추가합니다.

  1. struct Employee {
  2. name:String,
  3. company:String,
  4. age:u32
  5. }
  6.  
  7. let mut emp1 = Employee {
  8. company:String::from("TutorialsPoint"),
  9. name:String::from("Mohtashim"),
  10. age:50
  11. };
  12. emp1.age = 40;
  13. println!("Name is :{} company is {} age is
  14. {}",emp1.name,emp1.company,emp1.age);

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. Name is :Mohtashim company is TutorialsPoint age is 40

17.4 함수의 매개변수로서의 구조

구조의 용도 중 하나는 함수에 매개변수로 전달될 수 있다는 것입니다.

구조 매개변수를 정의하는 구문은 다른 유형의 매개변수를 정의하는 것과 동일합니다. 여기서는 많이 소개하지 않고 예시만 살펴보겠습니다.

다음 코드는 Employee 구조 인스턴스를 매개변수로 받아들이고 구조의 모든 요소를 ​​출력하는 함수 표시를 정의합니다.

  1. fn display( emp:Employee) {
  2. println!("Name is :{} company is {} age is
  3. {}",emp.name,emp.company,emp.age);
  4. }

전체 실행 가능한 예제 코드는 다음과 같습니다

  1. //구조 정의
  2. struct Employee {
  3. name:String,
  4. company:String,
  5. age:u32
  6. }
  7. fn main() {
  8. //초기화 구조
  9. let emp1 = Employee {
  10. company:String::from("TutorialsPoint"),
  11. name:String::from("Mohtashim"),
  12. age:50
  13. };
  14. let emp2 = Employee{
  15. company:String::from("TutorialsPoint"),
  16. name:String::from("Kannan"),
  17. age:32
  18. };
  19. //display 함수에 구조를 매개변수로 전달합니다.
  20. display(emp1);
  21. display(emp2);
  22. }
  23.  
  24. // 점(.) 접근자를 사용하여 구조체의 요소에 액세스하고 해당 값을 출력합니다.
  25. fn display( emp:Employee){
  26. println!("Name is :{} company is {} age is
  27. {}",emp.name,emp.company,emp.age);
  28. }

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. Name is :Mohtashim company is TutorialsPoint age is 50
  2. Name is :Kannan company is TutorialsPoint age is 32

17.5 함수의 반환값으로서의 구조체 인스턴스

Rust의 구조는 함수 매개변수로 사용될 수 있을 뿐만 아니라 함수 반환 값으로도 사용될 수 있습니다.

구조체 인스턴스를 반환하는 함수는 다음 두 위치를 구현해야 합니다.

  1. 화살표 -> 뒤에 반환 매개변수로 구조를 지정합니다.
  2. 함수 내에서 구조체의 인스턴스를 반환합니다.

17.5.1 함수의 반환값인 구조체 인스턴스의 구문 형식

  1. struct My_struct {}
  2.  
  3. fn function_name([parameters]) -> My_struct {
  4. // 기타 기능 로직
  5. return My_struct_instance;
  6. }

17.5.2 예

다음 코드에서는 먼저 Employee 구조를 정의한 다음 who_is_elder 메소드를 정의하고 두 구조 Employee를 매개변수로 전달하고 이전 구조를 반환합니다.

  1. fn main() {
  2.  
  3. let emp1 = Employee{
  4. company:String::from("TutorialsPoint"),
  5. name:String::from("Mohtashim"),
  6. age:50
  7. };
  8. let emp2 = Employee {
  9. company:String::from("TutorialsPoint"),
  10. name:String::from("Kannan"),
  11. age:32
  12. };
  13. let elder = who_is_elder(emp1,emp2);
  14. println!("elder is:");
  15.  
  16. display(elder);
  17. }
  18.  
  19. //두 개의 Employee 인스턴스를 매개변수로 받아들이고 이전 인스턴스를 반환합니다.
  20. fn who_is_elder (emp1:Employee,emp2:Employee)->Employee {
  21. if emp1.age>emp2.age {
  22. return emp1;
  23. } else {
  24. return emp2;
  25. }
  26. }
  27.  
  28. // 구조의 모든 요소 표시
  29. fn display( emp:Employee) {
  30. println!("Name is :{} company is {} age is {}",emp.name,emp.company,emp.age);
  31. }
  32.  
  33. // 구조 정의
  34. struct Employee {
  35. name:String,
  36. company:String,
  37. age:u32
  38. }

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. elder is:
  2. Name is :Mohtashim company is TutorialsPoint age is 50

17.6 구조체의 메소드

Rust의 구조는 메소드를 정의할 수 있습니다.

메소드는 특정 작업을 완료하거나 특정 기능을 구현하는 데 사용되는 코드 조각의 논리적 조합입니다.

방법과 기능의 차이점은 무엇입니까?

간단히 말해서:

  1. 함수에는 소유자, 즉 함수가 속한 사람이 없으므로 직접 호출할 수 있습니다.
  2. 메소드에는 소유자가 있으며 호출 시 소유자를 지정해야 합니다.
  3. 함수에는 소유자가 없으며 동일한 서명을 가진 두 개의 함수가 동일한 프로그램에 나타날 수 없습니다.
  4. 메소드에는 소유자가 있으며, 서로 다른 소유자가 동일한 서명을 가진 메소드를 가질 수 있습니다.

메소드를 정의할 때 fn 키워드가 필요합니다.

fn 키워드는 function의 첫 번째와 마지막 두 글자의 약어입니다.

 

구조 방법의 범위는 구조 내부 로 제한됩니다 .

C++ 언어의 구조체 메서드와 달리 Rust의 구조체 메서드는 구조체 외부에서만 정의할 수 있습니다.

구조체 메소드를 정의할 때 impl 키워드를 사용해야 합니다. 구문 형식은 다음과 같습니다.

  1. struct My_struct {}
  2.  
  3. impl My_struct {
  4. // 구조에 속하는 다른 모든 코드
  5. }

impl 키워드의 가장 중요한 역할은 위에서 언급한 메서드의 소유자를 정의하는 것입니다. impl My_struct 블록에 포함된 모든 코드는 My_struct 구조에만 속합니다.

impl 키워드는 Implement의 처음 4글자의 약어입니다. 깨닫는다 는 뜻입니다 .

구조체의 일반적인 메소드를 사용할 때(다른 메소드는 나중에 배우겠습니다) 첫 번째 매개변수는 항상 &self 키워드입니다. self는 "self"를 의미하며, &self는 항상 현재 구조의 인스턴스를 나타냅니다.

이는 다른 구조 방법에 대한 설명으로 이어지나요? 구조 방법은 현재 구조의 인스턴스를 작동하는 데 사용됩니다.

17.6.1 구조 메소드의 정의 구문

구조 메서드를 정의하는 구문 형식은 다음과 같습니다.

  1. struct My_struct {}
  2. impl My_struct {
  3.  
  4. // 구조를 정의하는 일반적인 방법
  5. fn method_name(&self[,other_parameters]) {
  6. //메소드의 특정 논리 코드
  7. }
  8.  
  9. }

&self는 구조체의 일반적인 메소드의 첫 번째 고정 매개변수이고, 다른 매개변수는 선택사항입니다.

구조 메소드가 매개변수를 전달할 필요가 없더라도 &self는 고정되어 존재해야 합니다. 다음과 같이 정의하는 것은 잘못되었습니다.

  1. struct My_struct {}
  2. impl My_struct {
  3.  
  4. //구조를 정의하는 일반적인 방법
  5. fn method_name([other_parameters]) {
  6. // 메소드의 특정 논리 코드
  7. }
  8. }

17.6.2 구조 메소드 내의 구조 요소에 접근하기

메소드를 정의할 때 &self 키워드를 고정적으로 전달했기 때문입니다. &self 키워드는 현재 메소드의 소유자를 나타냅니다.

따라서 메소드 내에서 self를 사용하여 구조의 요소에 액세스할 수 있습니다.

자세한 구문 형식은 다음과 같습니다

  1. struct My_struct {
  2. age: u32
  3. }
  4.  
  5. impl My_struct {
  6.  
  7. //구조를 정의하는 일반적인 방법
  8. fn method_name([other_parameters]) {
  9.  
  10. self.age = 28;
  11.  
  12. println!("{}",self.age);{}
  13.  
  14. //기타 특정 논리 코드
  15. }
  16. }

17.6.3 구조체 메소드의 구문 호출

구조체의 메소드에는 소유자가 있으므로 호출 시 먼저 소유자를 지정해야 합니다 . 호출 형식은 owner.method 이름(메서드 매개변수) 입니다 .

자세한 호출 구문 형식은 다음과 같습니다.

  1. My_struct.method_name([other_parameters])

메소드를 정의할 때 &self를 첫 번째 매개변수로 고정해야 하지만 호출할 때는 전달할 필요도 없고 전달할 수도 없습니다. Rust 컴파일러는 우리가 이 매개변수를 전달하도록 비밀리에 도와줄 것입니다.

17.6.4 예

다음 코드에서는 먼저 너비와 높이라는 두 가지 요소가 있는 사각형을 나타내기 위해 Rectangle 구조체를 정의합니다.

그런 다음 현재 직사각형 인스턴스의 면적을 계산하기 위해 Rectangle 구조에 대한 메소드 영역을 정의했습니다.

  1. // 직사각형 구조 정의
  2. struct Rectangle {
  3. width:u32, height:u32
  4. }
  5.  
  6. // 현재 직사각형의 면적을 계산하기 위해 직사각형 구조에 대한 방법을 정의합니다.
  7. impl Rectangle {
  8. fn area(&self)->u32 {
  9. //메소드 내에서 `self.` 점을 사용하여 현재 구조의 요소에 액세스할 수 있습니다. self 키워드를 통해 필드 값을 가져오려면 . 연산자를 사용하세요.
  10. self.width * self.height
  11. }
  12. }
  13.  
  14. fn main() {
  15. // Rectangle 구조의 인스턴스 만들기
  16. let small = Rectangle {
  17. width:10,
  18. height:20
  19. };
  20.  
  21. //구조물의 면적을 계산하고 출력합니다.
  22. println!("width is {} height is {} area of Rectangle
  23. is {}",small.width,small.height,small.area());
  24. }

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. width is 10 height is 20 area of Rectangle is 200

17.7 구조체의 정적 방법

Rust의 구조체에는 정적 메서드도 있을 수 있습니다.

정적 메서드는 먼저 인스턴스화하지 않고도 구조 이름에서 직접 호출할 수 있습니다.

구조체의 정적 메서드 정의는 일반 메서드와 유사하지만 &self를 매개 변수로 사용할 필요가 없다는 점만 다릅니다 .

17.7.1 정적 메서드 정의 구문

구조체의 정적 메서드를 정의하는 구문 형식은 다음과 같습니다.

  1. impl Structure_Name {
  2.  
  3. // Structure_Name 구조체의 정적 메서드
  4. fn method_name(param1: datatype, param2: datatype) -> return_type {
  5. // 메소드 내부 로직
  6. }
  7.  
  8. }

정적 메소드는 다른 일반 메소드와 유사하며 매개변수는 선택사항입니다. 즉, 매개변수가 있을 수 없습니다.

17.7.2 정적 메서드 호출 구문

정적 메서드는 먼저 인스턴스화하지 않고도 구조 이름에서 직접 호출할 수 있습니다.

구조체의 정적 메서드는 Structure_name:: 구문을 사용하여 액세스해야 합니다. 자세한 구문 형식은 다음과 같습니다.

  1. structure_name::method_name(v1,v2)

17.3 예

다음 예에서는 Point 구조에 대한 정적 메소드 getInstance()를 정의합니다.

  1.  // get_instance() Point 구조체의 인스턴스를 초기화하고 반환하는 팩토리 메서드입니다.
  2.  
  3. //구조 선언 Point
  4. struct Point {
  5. x: i32,
  6. y: i32,
  7. }
  8.  
  9. impl Point {
  10. // Point 인스턴스를 생성하기 위한 정적 메서드
  11. fn get_instance(x: i32, y: i32) -> Point {
  12. Point { x: x, y: y }
  13. }
  14. // 구조 요소를 표시하는 일반적인 방법
  15. fn display(&self){
  16. println!("x = {} y = {}",self.x,self.y );
  17. }
  18. }
  19. fn main(){
  20.  
  21. // 调用静态方法
  22. let p1 = Point::get_instance(10,20);
  23. p1.display();
  24.  
  25. }

위의 Rust 코드를 컴파일하고 실행하면 출력 결과는 다음과 같습니다.

  1. x = 10 y = 20
현재 콘텐츠 저작권은 chapin666 또는 그 계열사에 있습니다.
반응형

'Rust를 처음부터 배우세요' 카테고리의 다른 글

19. Rust 모듈  (0) 2024.11.27
18. Rust 열거 Enum  (0) 2024.11.20
16. Rust 슬라이스  (0) 2024.11.15
15. Rust는 차용(빌려줌) - Borrowing  (0) 2024.11.15
14. Rust 소유권  (0) 2024.11.15

관련글 더보기