LabVIEW 클래스 생성하기를 통해 사용자 정의 데이터 타입을 LabVIEW에 생성할 수 있습니다. LabVIEW 클래스는 객체와 관련된 데이터뿐만 아니라 데이터에 실행할 수 있는 동작을 정의하는 메소드를 정의합니다. 캡슐화 상속을 통해 사용자가 어플리케이션 상에서 코드에 영향을 미치지 않고 변경하기 용이한 모듈형 코드를 생성할 수 있습니다.

LabVIEW에서, 클래스의 데이터는 프라이빗으로서 클래스의 멤버인 VI만이 데이터에 접근할 수 있습니다. 프라이빗 데이터 컨트롤에서 클래스의 데이터를 정의합니다. LabVIEW 클래스를 생성하고 저장할 때, LabVIEW는 새로운 데이터 타입을 정의하는 클래스 라이브러리 파일 .lvclass를 생성합니다. 클래스 라이브러리 파일을 프라이빗 데이터 컨트롤과 VI 리스트 및 다양한 VI 프로퍼티 등의 사용자가 생성한 모든 멤버 VI의 정보를 기록합니다. 클래스 라이브러리는 프로젝트 라이브러리 .lvlib와 유사합니다. 그러나, 클래스 라이브러리는 새로운 데이터 타입을 정의합니다.

프라이빗 데이터 컨트롤은 고유한 클래스 라이브러리 파일로, 새로운 데이터 타입에 대한 데이터 클러스터를 정의하며 클래스 와이어 상의 데이터이기도 합니다. LabVIEW는 디스크에 프라이빗 데이터 컨트롤을 저장하지 않습니다. 대신, LabVIEW는 클래스 라이브러리 파일 안에 이를 저장합니다. 프라이빗 데이터 컨트롤을 클래스 라이브러리 파일 내에 저장하기 때문에 LabVIEW 사용자가 클래스 정의에 부합하지 않는 잘못된 프라이빗 데이터를 사용하는 경우는 없을 것입니다.

LabVIEW 클래스와 동일한 이름의 디렉토리를 디스크에 생성하여 클래스 라이브러리 파일, 클래스 멤버 VI 클래스 사용자 정의 기본 프로브를 저장할 수 있습니다. 디렉토리에 클래스 라이브러리가 소유하는 파일을 포함할 수 있습니다. 만일 하나 이상의 클래스 라이브러리를 동일한 디렉토리에 포함한다면, 같은 이름의 VI를 다른 클래스 라이브러리에 포함하려는 경우 충돌이 발생할 수 있습니다. 개발 프로세스에서 다이나믹 멤버 VI를 덮어쓰는 경우 이름과 관련된 충돌이 발생할 수 있습니다.

캡슐화

각 LabVIEW 클래스는 데이터 클러스터와 해당 클러스터를 읽고 쓰는 메소드로 구성되어 있습니다. LabVIEW 클래스 데이터는 항상 프라이빗이거나 클래스 멤버가 아닌 VI로부터 숨겨진 상태입니다. 프라이빗 데이터에 접근하려면, 클래스 멤버 VI 형태로 메소드를 생성하여 클래스 프라이빗 데이터에 함수를 사용합니다. 캡슐화는 오직 클래스 멤버 VI를 통해서만 데이터에 접근할 수 있는 클래스 안에 데이터와 메소드를 통합하는 것입니다. 캡슐화를 통해 사용자는 어플리케이션 내의 다른 코드 섹션에 영향을 미치지 않고 쉽게 업데이트하거나 변경할 수 있는 코드 모듈러 블록을 생성할 수 있습니다.

클래스 데이터가 항상 프라이빗이지만, 다양한 수준에서 멤버 VI를 사용자에게 공개할 수 있습니다. 다음의 옵션을 사용하여 메소드의 접근 영역을 설정할 수 있습니다:

  • 퍼블릭―모든 VI가 멤버 VI를 SubVI로 호출할 수 있습니다.
  • 공동 영역―같은 클래스에 있는 VI, 클래스의 friend, 클래스의 friend 라이브러리에 있는 VI만이 멤버 VI를 호출할 수 있습니다. 공동 영역 멤버 VI는 프로젝트 탐색기 윈도우에서 짙은 파란색 열쇠 문양으로 표시됩니다.
  • 보호됨―오직 동일한 클래스 혹은 하위 클래스에 속한 VI만 멤버 VI를 호출할 수 있습니다. 보호된 멤버 VI는 짙은 노란색 키 문양을 프로젝트 탐색기 윈도우에 디스플레이합니다.
  • 프라이빗―동일한 클래스에 속한 VI만 멤버 VI를 호출할 수 있습니다. 프라이빗 멤버 VI는 붉은색 키 문양을 프로젝트 탐색기 윈도우에 디스플레이합니다.
  • 미지정―이 옵션은 폴더를 선택할 때에만 나타납니다. 폴더에 지정된 접근 아이템이 없습니다. 접근은 퍼블릭입니다. 기본 설정으로, 클래스의 폴더는 지정된 접근을 가지고 있지 않으므로 폴더는 퍼블릭으로 접근이 가능합니다.
    노트 폴더에 대해 접근 옵션을 지정하는 경우, 접근 셋팅은 폴더의 모든 아이템에 적용되고 폴더의 개별 아이템에 대한 접근 옵션을 덮어씁니다.
노트 공동 영역으로 설정하면 다이나믹 디스패치 VI는 깨집니다. 보호된 영역에 있는 다이나믹 디스패치 VI에 friend 접근 권한을 부여하려면, friend가 호출하는 정적 디스패치 래퍼 VI를 생성하고 이 래퍼 VI를 공동 영역으로 설정합니다.

라이브러리의 Friend 지정하기

VI가 공동 영역에 있는 라이브러리의 모든 멤버를 호출할 수 있게하려면, VI를 라이브러리의 friend로 지정합니다. 또한 다른 라이브러리를 라이브러리의 friend로 지정할 수 있습니다.

Friend 속성(friendship)은 전달(transitive)되지 않습니다. 예를 들어, 첫번째 라이브러리가 두번째 라이브러리를 friend로 지정하고, 이 두번째 라이브러리가 세번째 라이브러리를 friend로 명명한 경우, 세번째 라이브러리는 첫번째 라이브러리의 friend로 간주되지 않습니다. 첫 번째 라이브러리가 세 번째 라이브러리를 friend로 할당하지 않으면, 세 번째 라이브러리는 첫 번째 라이브러리의 VI에 접근할 수 없습니다. 공동 영역에 있는 라이브러리가 클래스를 friend로 지정하면 이 클래스의 멤버 VI는 이 라이브러리의 VI에 접근할 수 있습니다. 그러나 이 friend 속성(friendship)은 클래스의 하위로는 확대되지 않습니다.

LabVIEW 클래스 밖에서 VI를 생성하고 블록다이어그램에서 퍼블릭 멤버 VI를 SubVI로 사용할 수 있습니다. 퍼블릭 멤버 VI를 사용하면 클래스의 프라이빗 데이터를 조작할 수 있습니다. 멤버 VI의 블록다이어그램에서 프라이빗 및 보호된 멤버 VI를 사용하여 LabVIEW 클래스 사용자에게 공개되지 않은 클래스의 프라이빗 데이터를 조작할 수 있습니다. 클래스 밖의 VI를 클래스의 friend로 지정하여, friend VI에게 클래스의 공동 영역 멤버를 호출하는 권한을 부여할 수 있습니다. 클래스의 출입 포인트를 제한하면 데이터에 오류가 발생할 확률이 줄어들기 때문에 코드 디버깅을 용이하게 할 수 있습니다.

LabVIEW 클래스에서의 캡슐화 및 접근 영역 예제는 다음의 프로젝트를 참조합니다.

  • labview\examples\Object-Oriented Programming\Data Encapsulation\Data Encapsulation with LabVIEW Classes.lvproj
  • labview\examples\Object-Oriented Programming\Access Scope\Access Scope with LabVIEW Classes.lvproj

프라이빗 데이터 컨트롤 정의하기

LabVIEW는 사용자가 LabVIEW 클래스를 생성할 때 자동으로 클래스의 프라이빗 데이터 컨트롤을 생성합니다. 다음의 프로젝트 탐색기 윈도우에서 LabVIEW 클래스 아이콘이 유색 큐브임을 확인하십시오. 이 큐브는 LabVIEW 클래스를 나타냅니다. 프라이빗 데이터 컨트롤 아이콘은 초록색 원기둥이 있는 유색 큐브입니다. 이 원기둥은 데이터 스토리지를 나타냅니다. 프라이빗 데이터 컨트롤 아이콘 또한 컨트롤이 프라이빗임을 나타내는 붉은색 키 문양을 디스플레이합니다.

컨트롤 편집기 윈도우를 사용하여 클래스의 프라이빗 데이터 컨트롤을 사용자 정의할 수 있습니다. 프로젝트 탐색기 윈도우 클래스의 프라이빗 데이터 컨트롤을 더블 클릭하면 LabVIEW는 컨트롤 편집기 윈도우를 디스플레이합니다. 클래스 프라이빗 데이터의 클러스터 안에 컨트롤과 인디케이터를 놓으면 LabVIEW 클래스의 프라이빗 데이터 타입을 정의할 수 있습니다. 클래스 프라이빗 데이터의 클러스터 안의 컨트롤에 설정한 기본값은 클래스의 기본값입니다.

노트 프라이빗 데이터 컨트롤은 X컨트롤을 포함할 수 없습니다.

다음 예에서, Vehicle 클래스의 데이터 타입은 기어 개수, 차문 개수, 이라는 세 숫자형과 차종모델이라는 두 문자열을 포함합니다.

노트 클래스가 프라이빗 데이터를 필요로 하지 않는 경우 클래스 프라이빗 데이터의 클러스터를 빈 상태로 남겨놓을 수 있습니다.

블록다이어그램이나 프런트패널에서 클래스의 객체를 시각적으로 나타내는 아이콘을 생성할 수 있습니다. 클래스 프로퍼티 대화 상자의 일반 셋팅 페이지에 있는 편집 버튼을 클릭하여 아이콘 편집기 대화 상자를 시작합니다. 클래스 아이콘을 생성합니다. 그러면 LabVIEW는 이 아이콘을 클래스에 있는 모든 개체에 적용합니다. 그런 다음에 클래스에 있는 각각의 개체에 대해 개별적으로 아이콘을 변경합니다.

멤버 VI 생성하기

멤버 VI를 생성하여 클래스의 프라이빗 데이터에 작업을 수행합니다. 멤버 VI는 LabVIEW 클래스의 메소드입니다. 멤버 VI는 멤버 VI를 생성한 LabVIEW 클래스의 멤버로, 클래스의 프라이빗 데이터 컨트롤 밑의 프로젝트 탐색기 윈도우에 나타납니다.

LabVIEW는 클래스의 데이터를 클러스터로 정의합니다. 모든 멤버 VI는 클래스 데이터의 클러스터를 읽고 쓸 수 있습니다. LabVIEW는 클러스터의 개별 원소에 접근하는 VI를 생성하는 바로 가기를 제공합니다. 이러한 접근자 VI는 LabVIEW 클래스의 멤버이며 클래스 데이터를 읽고 쓸 수 있습니다. 접근자 VI를 생성하여 클래스 데이터를 읽는 경우, LabVIEW는 다음 이미지와 같이 클래스 데이터를 풉니다.

접근자 VI를 생성하여 클래스 데이터에 쓰는 경우, LabVIEW는 다음 이미지와 같이 새 값을 클래스 데이터에 묶습니다.

또한 [풀기][이름으로 풀기] 함수를 사용하여 멤버 VI의 블록다이어그램에 있는 클래스의 프라이빗 데이터를 풀 수 있습니다. [묶기][이름으로 묶기] 함수를 사용하여 사용자가 접근하고 조작한 프라이빗 데이터의 클러스터를 다시 묶습니다. 클래스의 데이터가 프라이빗이기 때문에, 멤버가 아닌 VI의 블록다이어그램에 있는 클래스 데이터와 함께 사용하려고 하면 [묶기]와 [풀기] 노드는 깨집니다.

노트 새 원소를 프라이빗 데이터에 끼워 넣는 경우, 되도록이면 [묶기] 및 [풀기] 함수 대신 [이름으로 묶기] 및 [이름으로 풀기] 함수를 사용하여 VI가 깨지는 것을 방지하도록 합니다.

어떤 값을 풀고, 변경한 후, 다시 객체로 묶는 멤버 VI를 작성하는 경우에는, 구조 경계에 한 쌍의 [풀기]와 [묶기] 노드가 있는 In Place 원소 구조를 사용하는 것이 더 효율적일 수 있습니다. 구조를 사용하면, LabVIEW는 특정 메모리 최적화 전략을 적용하게 됩니다. 일반 [풀기] 및 [묶기] 노드를 사용할 때 이와 똑같은 메모리 최적화 전략이 적용될 수도 있습니다. 하지만, 복잡한 VI를 사용하는 일부 상황에서는 LabVIEW 컴파일러가 관련 최적화 전략의 안전성을 신뢰하지 못해서 이를 적용하지 않고, 결과적으로 메모리 성능을 저해할 가능성이 있습니다. 구조 노드는 이러한 최적화 전략의 안정성을 보장하기 때문에, 반드시 VI에 대한 최적화 전략이 적용됩니다.

멤버 VI는 여러 가지 방법으로 생성할 수 있습니다. 클래스에서 마우스 오른쪽 버튼을 클릭하고 다음의 바로 가기 메뉴 아이템에서 선택하십시오:

  • 새로 만들기≫VI―새 멤버 VI를 엽니다.
  • 새로 만들기≫프로퍼티 정의 폴더—새 멤버 VI를 만들거나, 기존 멤버 VI를 추가할 수 있는 프로퍼티 정의 폴더를 생성합니다. LabVIEW 클래스에 프로퍼티 정의 폴더가 있을 경우, LabVIEW 클래스를 프로퍼티 노드에 연결해서 프라이빗 데이터에 접근할 수 있습니다.
  • 새로 만들기≫다이나믹 디스패치 템플릿으로부터 VI―LabVIEW는 에러 입력에러 출력 클러스터, 에러 핸들링을 위한 케이스 구조, 입력 LabVIEW 클래스, 출력 LabVIEW 클래스로 새 멤버 VI를 채웁니다. LabVIEW는 입력 및 출력 터미널 모두를 VI 커넥터 팬에서 다이나믹한 것으로 설정합니다.
  • 새로 만들기≫정적 디스패치 템플릿으로부터 VI―LabVIEW는 에러 입력에러 출력 클러스터, 에러 핸들링을 위한 케이스 구조, 입력 LabVIEW 클래스, 출력 LabVIEW 클래스로 새 멤버 VI를 채웁니다. 다이나믹 디스패치 VI와 달리, LabVIEW는 정적 디스패치 VI의 커넥터 팬에서 입력과 출력 터미널을 다이나믹으로 설정하지 않습니다.
  • 새로 만들기≫데이터 멤버 접근을 위한 VI접근자 생성 대화 상자를 엽니다. 이 대화 상자를 사용하여 LabVIEW 클래스 데이터에 접근할 수 있는 멤버 VI를 신속하게 생성합니다.
    노트 이 옵션을 사용하기 전에 새 LabVIEW 클래스를 저장해야 합니다. 새 클래스를 저장하지 않으면 LabVIEW는 데이터 멤버 접근을 위한 VI 옵션을 비활성시킵니다.
  • 새로 만들기≫덮어쓰기 위한 VI―상위 멤버 VI를 덮어쓰는 멤버 VI를 생성합니다. LabVIEW는 상위 VI 아이콘을 사용하며 직하위 클래스의 아이콘 마스크를 덮어써서 새 VI의 아이콘을 생성합니다.
    노트 덮어쓸 수 있는 유효한 멤버 VI가 없는 경우 LabVIEW는 새로 만들기≫덮어쓰기 위한 VI 옵션을 비활성화합니다. 상속 섹션에서 다이나믹 VI와 덮어쓰기에 대한 추가 정보를 참조하십시오.

프런트패널 또는 블록다이어그램의 클래스 상수, 컨트롤 또는 인디케이터에서 마우스 오른쪽 버튼을 클릭한 후, 바로 가기 메뉴에서 클래스 라이브러리 보이기를 선택하여 프로젝트 탐색기 윈도우의 클래스를 하이라이트합니다. 작업하는 클래스가 LabVIEW 프로젝트에 없으면, LabVIEW는 클래스 윈도우를 열어 클래스를 디스플레이합니다.

상속

상속은 기존의 클래스를 새 클래스의 시작 포인트로 사용할 수 있도록 합니다. 새로 LabVIEW 클래스를 생성하고 다른 클래스로부터 데이터와 멤버 VI를 상속받도록 설정하면, 새 클래스는 상속하는 클래스의 퍼블릭 및 보호된 멤버 VI를 사용할 수 있습니다. 또한 자신의 데이터와 멤버 VI를 추가하여 기능을 확장합니다. 예를 들어, Vehicle 클래스의 프라이빗 데이터는 기어 개수차문 개수, , 차종, 모델을 포함합니다. 만일 Truck이라는 이름을 가진 새로운 클래스를 생성한다면, Truck 클래스가 Vehicle 클래스의 데이터를 상속하도록 설정 할 뿐만 아니라, 간이 침대?사륜 구동?이라는 불리언 데이터를 추가할 수 있습니다. 하지만, 다음 그림에서 알 수 있듯이, LabVIEW 클래스를 묶거나 풀 때 노드는 오직 현재 클래스의 프라이빗 데이터의 터미널만을 보여줄 뿐, 상위 클래스에서 상속한 클래스 데이터의 터미널은 모두 나타내지 않습니다.

상위 데이터는 프라이빗이고, 멤버 VI를 통해 상위 클래스가 제공하는 함수를 사용해서 이를 수정할 수 있습니다. 하위 클래스의 멤버 VI는 LabVIEW 상의 여느 VI처럼 어떤 퍼블릭 멤버 VI든지 호출할 수 있습니다. 하지만 하위 클래스 멤버 VI 또한 상위 클래스의 보호된 멤버 VI를 호출할 수 있습니다. 상위 멤버 VI를 보호된 VI로 지정할 때, 어떤 직하위 클래스의 멤버 VI든지 메소드를 호출할 수 있지만 상속 계층구조 밖에 있는 VI는 이와 같이 호출할 수 없습니다. Truck 클래스에서 Vehicle 클래스의 기어 개수에 접근하고자 한다면, Vehicle 클래스에 Get Gears.vi라고 불리는 퍼블릭 혹은 보호된 멤버 VI를 생성할 수 있습니다. Get Gears.vi의 블록다이어그램에서 Vehicle 클래스 풀기를 실행하여 기어 개수를 나타낼 수 있습니다. 그 후 기어 개수를 커넥터 팬의 출력 터미널에 지정하면, 이를 통해 Truck 클래스와 같은 하위 클래스에서 Vehicle 클래스의 특정 프라이빗 데이터에 접근할 수 있습니다.

Vehicle 클래스의 데이터 멤버에 접근하도록 멤버 VI를 생성해서 기어 갯수에 접근할 수 있습니다. 멤버 VI를 생성할 때, 접근자 생성 대화 상자에서 프로퍼티 노드에서 이용 가능 확인란에 확인 표시를 합니다. 그 후 Truck 클래스를 프로퍼티 노드에 연결하고, 프로퍼티 터미널에서 마우스 오른쪽 버튼을 클릭해서 프로퍼티 선택≫기어 갯수를 선택할 수 있습니다.

노트 LabVIEW 클래스는 비록 직상위 클래스더라도 다른 LabVIEW 클래스의 프라이빗 멤버 VI를 호출할 수 없습니다. 동일한 클래스에 있는 다른 멤버 VI의 블록다이어그램에 있는 프라이빗 멤버 VI만을 사용할 수 있습니다.
노트(FPGA Module) FPGA VI를 생성할 때 특정 제한이 있는 상속을 사용할 수 있습니다.

LabVIEW 객체

LabVIEW 객체라는 구문은 특정 클래스의 이름입니다. LabVIEW 객체는 LabVIEW의 객체 지향 프로그래밍의 상속 트리에서 최상위입니다. 기본적으로, 모든 LabVIEW 클래스는 LabVIEW 객체로부터 상속됩니다. LabVIEW 객체를 사용하여 여러 LabVIEW 클래스에서 일반적인 작업을 실행하는 VI를 생성할 수 있습니다. 예를 들어, LabVIEW 클래스 배열을 생성한 경우, 배열의 클래스 타입 또는 어떤 하위 클래스의 원소를 포함할 수 있기 때문에 배열의 데이터는 서로 다릅니다. 배열이 LabVIEW 객체 타입인 경우, 운송 수단(Vehicle), 트럭(Truck), 볼링 볼(Bowling Ball) 등을 포함할 수 있습니다. Bowling Ball 클래스는 Vehicle이나 Truck 클래스에서 상속되지 않았기 때문에, 이 경우에 LabVIEW는 가장 일반적인 상위 기본 클래스인 LabVIEW 객체의 배열을 생성합니다.

다음 이미지는 Vehicle 및 Truck 클래스를 포함하는 Vehicle 배열을 보여줍니다. Truck이 Vehicle로부터 상속했기 때문에, 이 배열의 일반 상위 기본 클래스는 Vehicle 타입입니다. 이미지는 또한 LabVIEW Object, Vehicle, Truck, Bowling Ball 클래스를 포함하는 LabVIEW 객체 배열을 디스플레이합니다. Bowling Ball은 Vehicle이나 Truck으로부터 상속받지 않으나, 세 클래스 모두 궁극적으로 LabVIEW Object로부터 상속받습니다. 따라서, LabVIEW 객체 배열은 LabVIEW Object 타입입니다.

상속 설정하기

모든 LabVIEW 클래스는 기본적으로 LabVIEW 객체로부터 상속됩니다. 다른 클래스에게 상속하는 클래스를 변경하고자 하는 경우, 관련된 클래스를 생성한 후에 상속 변경을 해야 합니다. 클래스 프로퍼티 대화 상자에서 상속 및 다른 클래스 옵션을 설정할 수 있습니다. LabVIEW 클래스 계층구조 윈도우에서 LabVIEW 클래스 계층구조 보기를 할 수 있습니다. 클래스 상속 계층구조는 다음 타입의 클래스를 포함할 수 있습니다:

  • 직상위 클래스(Parent class)― 다른 LabVIEW 클래스에게 데이터, 퍼블릭 및 보호된 멤버 VI를 상속하는 LabVIEW 클래스.
  • 직하위 클래스(Child class)― 직상위 클래스의 퍼블릭 및 보호된 멤버 VI를 상속받는 LabVIEW 클래스. 직상위 클래스가 접근자 VI를 제공하지 않으면, 직하위 클래스는 프라이빗 데이터를 상속하지 않습니다.
  • 등위 클래스(Sibling class)― 다른 LabVIEW 클래스와 동일한 직상위 클래스를 공유하는 LabVIEW 클래스.
  • 상위 클래스(Ancestor class)― 다른 LabVIEW 클래스의 직상위(parent), 직상위의 상위(grandparent), 직상위 상위의 상위(great-grandparent), 그리고 어떤 형식으로든 상위인 LabVIEW 클래스. LabVIEW 객체는 모든 LabVIEW 클래스의 궁극적인 최상위입니다.
  • 하위 클래스(Descendant class)― 다른 LabVIEW 클래스의 직하위(child), 직하위의 하위(grandchild), 직하위 하위의 하위(great-grandchild), 그리고 어떤 형식으로든 하위인 LabVIEW 클래스.
노트 직상위 클래스의 프로퍼티 접근자 VI를 덮어쓰는 VI를 생성하는 경우, 직하위 및 직상위 클래스의 프로퍼티 정의 폴더는 동일한 이름 및 폴더 경로를 가져야 합니다.

와이어 모양

클래스는 새로운 데이터 타입을 정의합니다. 이런 클래스 타입의 와이어는 블록다이어그램에서 기본 LabVIEW 클래스 와이어로 나타나거나 직상위 클래스의 와이어 모양을 상속합니다. 클래스 프로퍼티 대화 상자에서 LabVIEW 클래스의 와이어 모양을 변경할 수 있습니다. 읽기 쉬운 블록다이어그램을 생성하기 위해, 적절한 경우에 서로 다른 LabVIEW 클래스의 와이어 모양을 변경할 수 있습니다. 지나치게 많은 와이어 색과 패턴은 블록다이어그램을 읽는 것을 어렵게 할 수 있습니다. 다음 이미지를 보면 왼편에서 LabVIEW에 내장된 와이어 모양을 그리고 오른편에서 사용자 정의된 와이어 모양의 예를 확인할 수 있습니다.

LabVIEW에서 지나치게 복잡한 와이어 패턴 또는 색을 사용하지 않기 위한 추가적인 팁은 LabVIEW Style Checklist를 참조하십시오.

다이나믹 및 정적 디스패치 멤버 VI

메소드란 객체에 대해 수행하거나 객체에 의해 수행되는 동작을 지칭합니다. LabVIEW 객체 지향 프로그래밍에서, 메소드는 사용자가 생성하는 멤버 VI입니다. 멤버 VI는 LabVIEW 클래스의 데이터에서 동작합니다. 단일 VI에서 일부 메소드를 정의할 수 있습니다. LabVIEW가 항상 동일한 VI를 호출하기 때문에, 이러한 메소드는 정적 디스패치 메소드라고 합니다. 또한 클래스 계층구조에서 동일한 이름의 여러 VI를 통해 메소드를 정의할 수 있습니다. 런타임 전에는 LabVIEW가 VI 세트에서 정확히 어떤 VI를 호출하는지 알 수 없기 때문에, 이는 다이나믹 디스패치 메소드라고 합니다. 다이나믹 디스패치 메소드는 다형성 VI와 유사합니다. 다형성 VI는 사용자가 연결하는 데이터 타입에 따라 어떤 VI를 호출할지 구분하는 반면에, 다이나믹 디스패치 메소드는 런타임이 시작될 때까지 대기한 후 입력 터미널에 도착하는 데이터에 따라 클래스 계층구조에서 호출할 멤버 VI를 결정합니다.

멤버 VI가 정적일지 또는 다이나믹일지의 여부는 멤버 VI의 커넥터 팬에서 사용자가 지정합니다. 커넥터 팬이 다이나믹 디스패치 입력 터미널을 포함하는 경우, 이 멤버 VI는 다이나믹 디스패치 메소드의 일부입니다. 다이나믹 디스패치 입력 터미널이 없는 경우, 이 멤버 VI는 정적 디스패치 메소드를 정의합니다.

하나의 LabVIEW 클래스가 다른 LabVIEW 클래스로부터 상속하는 경우, 직하위 클래스는 직상위 클래스에 정의된 모든 퍼블릭 및 보호된 메소드를 상속합니다. 직하위 클래스의 멤버 VI를 직상위 클래스의 멤버 VI와 완전히 동일한 이름으로 지정함으로써 직하위에서 메소드가 어떻게 구현될지도 정의됩니다.

LabVIEW의 정적 디스패치 메소드는 단일 VI에 의해 정의되는 것이기 때문에, 상위 클래스의 정적 디스패치 멤버 VI와 동일한 이름으로 직하위 클래스 멤버 VI의 이름을 지정하지 마십시오. 예를 들어, 만약 직상위인 Vehicle 클래스에 Open Door VI라는 정적 디스패치 멤버 VI가 포함되어 있다면, 직하위인 Truck 클래스는 Open Door VI라는 멤버 VI를 가질 수 없습니다. Truck은 Vehicle에서 멤버 VI를 상속하기 때문에 Open Door VI는 Truck에서 이미 정의되어 있습니다. 정적 디스패치 멤버 VI를 블록다이어그램 상에서 SubVI처럼 놓는다면, 모든 점에서 일반 SubVI 호출처럼 동작합니다.

여러 개의 다이나믹 디스패치 VI 메소드를 상속 계층구조의 각 레벨마다 하나씩 정의할 수 있습니다. 다이나믹 디스패치 VI가 직상위 클래스에서 정의되었고 사용자 또한 이를 직하위 클래스에서 정의하는 경우, 직하위 클래스에서의 구현이 직상위의 구현을 덮어쓰거나 확장시킵니다. 다음의 예에서, Vehicle 클래스와 Truck 클래스 모두 다이나믹 디스패치 메소드인 Set Make VI의 실행을 정의합니다. 블록다이어그램에 다이나믹 디스패치 VI를 SubVI로 놓는다면, 블록다이어그램의 노드는 LabVIEW가 편집 모드에 있을 때 호출하는 일반 SubVI처럼 작동합니다. 그러나 VI를 실행한다면, 다이나믹 디스패치 입력 터미널에 들어오는 데이터가 LabVIEW가 호출하는 클래스 계층구조 내 다이나믹 멤버 VI의 실행을 결정합니다. LabVIEW 클래스 와이어가 자신의 타입 혹은 직하위 타입 데이터를 전달할 수 있기 때문에, 노드는 사용자가 클래스 데이터로 정의한 모든 다이나믹 디스패치 VI를 실행합니다. 다음 예제를 다시 한 번 검토하십시오. Set Make VI로 구현한 Vehicle 클래스만 Main VI의 블록다이어그램에 있습니다. 루프의 첫번째 반복에서 LabVIEW는 Vehicle 클래스의 데이터가 클래스 와이어에 있기 때문에 Set Make VI로 구현한 Vehicle 클래스를 실행합니다. 루프의 두번째 반복에서 LabVIEW는 트럭 클래스의 데이터가 클래스 와이어에 있기 때문에 차종 설정 VI의 트럭 클래스를 실행합니다.

직상위 클래스가 다이나믹 디스패치 VI를 정의하지만 그 VI를 구현하지 않는 경우, 각 직하위 클래스가 직상위 VI를 덮어써야 합니다. 많은 경우, 사용자가 직상위 클래스 VI에서 의미있는 동작을 제공하는 것이 불가능합니다. 예를 들어, Area VI를 정의하는 Shape이라는 클래스가 있다고 가정해봅니다. Area VI는 Shape 객체에서 모양의 넓이을 반환합니다. 모든 모양, 심지어는 대다수 모양의 넓이 연산할 수 있는 단 하나의 수식은 존재하지 않습니다. 따라서, 각 하위 클래스는 모양에 대응하는 수식으로 Area VI를 덮어써야 합니다. 그 결과, Circle이라는 직하위 클래스를 생성하는 경우, Circle 클래스는 pi*반지름*반지름을 계산하는 Area VI를 제공해야 합니다.

직상위 클래스 VI의 구현을 정의하지 않은 경우, 직상위 VI는 단순히 커넥터 팬를 정의하고 직상위 VI를 덮어써야하는 다른 VI가 모두 일치시켜야 할 VI 프로퍼티를 정의할 뿐입니다. 각 직하위 클래스는 이를 덮어쓰는 VI를 제공해야 합니다. LabVIEW가 이 요구사항을 적용하도록 하려면, 직상위 클래스에 있는 VI를 표시해서 각 직하위 클래스가 덮어써야 하는 VI로 설정하고 이 요구조건을 LabVIEW가 적용하도록 만듭니다.

일부 직하위 클래스는 멤버 VI의 기능을 덮어쓰지 못할 수도 있습니다. 예를 들어, Shape(모양) 클래스의 직하위 클래스로 Quadrilateral(사각형)이 있는경우, 이 직하위 클래스에 속하는 사각형이 어떤 종류인지 모르면 그 넓이를 계산할 정확한 수식을 제공할 수 없습니다. Quadrilateral 클래스 안에서 Area VI가 구현될 때 값을 생성하지 못하는 경우가 없도록, Quadrilateral 클래스가 직하위 클래스에 덮어쓰기 요청을 전송하도록 지시할 수 있습니다. 이를 위해, 직하위 클래스에서 마우스 오른쪽 버튼을 클릭한 후 바로 가기 메뉴에서 프로퍼티를 선택하여 클래스 프로퍼티 대화 상자를 디스플레이합니다. 상속 페이지에서 모든 덮어쓰기 요청을 하위 클래스에 전송 확인란에 확인 표시를 합니다. 그러면 LabVIEW에서 Trapezoid, Rectangle과 같은 Quadrilateral 클래스의 직하위 클래스들이 Area VI를 덮어쓰게 됩니다.

하위 클래스가 직상위 클래스 멤버 VI를 덮어쓰도록 요청한다고 멤버 VI가 실행되는 방식에 영향을 미치지 않습니다.

노트 LLB는 동일한 이름의 파일을 가질 수 없습니다. 따라서 클래스 계층구조에서 동일한 이름을 갖는 다이나믹 멤버 VI들이 있다면, 같은 LLB에 이 클래스들을 넣을 수 없습니다.

노트 직하위 클래스의 VI가 직상위 클래스의 VI를 덮어쓸 때, 직하위의 VI는 직상위의 VI와 재호출 셋팅, 선호하는 실행 셋팅, 우선 순위 셋팅, 커넥터 팬 터미널, 커넥터 팬 패턴, 접근 영역이 일치해야 합니다.

블록다이어그램의 다이나믹 디스패치 SubVI를 더블 클릭하고 구현 대상 선택 대화 상자를 디스플레이합니다. 이 대화 상자를 사용하여 현재 메모리에 있는 다이나믹 디스패치 SubVI의 모든 구현 대상을 본 후 SubVI의 하나 또는 그 이상의 구현 대상 열기를 합니다.

새로 만들기≫덮어쓰기 위한 VI를 선택하여 다이나믹 디스패치 멤버 VI의 상위 구현을 덮어쓸 VI를 생성하는 경우, 또다른 다이나믹 디스패치 멤버 VI를 생성하게 됩니다. 왜냐하면, 상위 멤버 VI를 덮어쓰는 VI는 상위와 똑같은 이름을 갖고 또한 다이나믹 디스패치 터미널을 포함하기 때문입니다. LabVIEW는 [직상위 클래스 메소드 호출] 노드를 적절한 다이나믹 디스패치 입력 및 출력 클래스 터미널과 VI가 상위 VI와 일치하기 위해 필요한 다른 터미널과 함께 블록다이어그램에 놓습니다. LabVIEW는 덮어쓸 상위 멤버 VI가 없는 경우 덮어쓰기 위한 VI 옵션을 비활성화합니다.

노트(FPGA Module) FPGA VI를 생성할 때 특정 제한이 있는 다이나믹 디스패치를 사용할 수 있습니다.

다이나믹 디스패치 출력

커넥터 팬의 출력 터미널에서 마우스 오른쪽 버튼을 클릭한 후 다이나믹 디스패치 출력 (권장)을 선택하여 LabVIEW 클래스 출력 터미널을 다이나믹으로 설정할 수 있습니다. 다이나믹 디스패치 출력 터미널이 있는 VI를 SubVI로 호출하면, 다이나믹 디스패치 출력은 다이나믹 디스패치 입력 터미널에 연결된 와이어와 같은 데이터 타입으로 변경됩니다. 한 예로, Vehicle 클래스의 와이어를 다이나믹 디스패치 입력 터미널에 연결하면, 멤버 VI의 출력은 입력과 같습니다. 이 경우 출력은 Vehicle 클래스입니다. 사용자는 다이나믹 디스패치 입력 터미널과 다이나믹 디스패치 출력 터미널 사이에 있는 데이터를 수정할 수 있습니다. 그러나, LabVIEW 클래스의 런타임 안정성을 보장하려면, 다이나믹 디스패치 입력 터미널으로부터의 데이터는 모든 다이나믹 디스패치 출력 터미널로 연결되야 합니다. 또한, LabVIEW가 정확히 한 번에 다이나믹 디스패치 입력 터미널로부터 읽기를 하고 다이나믹 디스패치 출력 터미널로 쓰기를 하도록 하기 위해서, 사용자는 다이나믹 디스패치 블록다이어그램 터미널을 구조 안에 놓을 수 없습니다.

노트 다이나믹 디스패치 입력과 출력이 있는 다이나믹 디스패치 멤버 VI를 디버깅하고 있다면, 다이나믹 디스패치 입력에서 출력으로 연결되는 와이어에 에러가 있는지 확인할 수 있습니다. 다이나믹 입력에서 시작하는 와이어가 런타임 데이터 타입을 변경할 수 있는 어떤 함수도 통과하지 않는 경우, 와이어 배경색은 보통의 흰색이 아닌 회색으로 나타납니다. 와이어가 데이터 타입을 변경할 수 있는 함수를 통과하는 경우, 와이어 배경색은 빨간색으로 바뀝니다. 다이나믹 출력이 바르게 작동하려면, LabVIEW 클래스의 데이터 타입을 바꿔서는 안됩니다.

LabVIEW 클래스 출력 데이터가 입력과는 다르게 나타날 작업을 멤버 VI의 블록다이어그램에서 완성하려는 경우, 커넥터 팬의 LabVIEW 클래스 다이나믹 디스패치 터미널이 다이나믹 디스패치 출력(권장)이 아닌 권장으로 설정되었는지 확인합니다. 한 예로, LabVIEW 클래스 입력이 Vehicle이고 LabVIEW 클래스 출력이 Truck이기를 사용자가 원한다면, 커넥터 팬에서 LabVIEW 클래스의 기본 터미널을 변경해야 합니다. 다른 방법으로, 새 VI를 사용하여 멤버 VI 생성을 해서 수동으로 커넥터 팬 터미널을 설정할 수 있습니다.

노트 다이나믹 디스패치 입력과 출력이 있는 멤버 VI의 케이스 또는 이벤트 구조를 사용하는 경우, 출력 터널에서 연결되지 않으면 기본값 사용를 선택할 수 없습니다. 출력 터널에서 연결되어 있지 않으면 기본 사용을 사용하면, LabVIEW는 VI를 깨뜨립니다. 구조 안에 있는 모든 케이스를 반드시 연결해야 합니다. 자동으로 입력 및 출력 터널이 연결되도록 터널을 설정하는 방법도 있습니다.

다이나믹 디스패치를 위한 메모리 복사본의 최적화

위에서 설명한 것처럼, 다이나믹 디스패치 메소드를 생성할 때, 각 직하위 클래스는 직상위 클래스에서 정의한 퍼블릭 및 보호된 메소드를 모두 상속합니다. 직상위 클래스는 이러한 멤버 VI를 자체적인 버전으로 덮어쓰거나 확장시킬 수 있습니다. VI가 다이나믹 디스패치 메소드를 호출할 때, LabVIEW는 런타임이 될 때까지 어느 버전의 메소드를 가져오게 될지를 알지 못합니다. 따라서 LabVIEW는 호출자 VI의 메모리 할당을 최적화하여, 직하위 클래스가 포함하는 멤버 VI는 모두 직상위 클래스에 있는 멤버 VI와 똑같이 설정될 것이라고 가정합니다. 직상위 VI에서 입력이 상수인 경우, 호출자 VI는 직하위 VI에서도 이 입력이 상수라고 가정합니다. 직상위 클래스 멤버 VI에서 입력이 출력을 반환하는 경우, 호출자 VI는 이 입력이 모든 직하위 클래스 멤버 VI에서도 똑같은 동작을 취할 것으로 가정합니다.

이러한 가정 중 어느 하나라도 틀린다면, 최적화 동작은 소용없게 됩니다. 예를 들어, 사용자가 변경되지 않은 여러 입력을 포함하는 멤버 VI를 생성하는 경우, 호출자 VI는 이 입력들이 앞으로 영원히 변경되지 않을 것이라고 가정합니다. 하지만, 어떤 덮어쓰기 동작이든지 모두 일부 또는 전체 입력을 변경할 수 있습니다. 또 다른 예로, 직상위 클래스 멤버 VI에서 어떤 입력도 출력에 와이어로 연결하지 않은 경우, 호출자 VI는 입력과 메모리를 공유하는 출력이 하나도 없다고 가정합니다. 하지만, 이후에 이어지는 멤버 VI에서 입력이 출력에 연결될 수도 있습니다. LabVIEW는 직하위 클래스에서 기대하지 않은 동작이 발생할 때 이를 처리할 코드를 생성해야 하며, 이로 인해 최적화 동작의 효율성이 떨어지게 됩니다.

직하위 클래스 VI에서 발생 가능한 모든 경우를 반영하여, 최대한 일관성 있는 직상위 클래스 VI를 작성함으로써 최적화 전략을 더욱 개선할 수 있습니다. 각 터미널에서 예상하지 못한 동작을 정확하게 나타낼 수 있는 다이나믹 디스패치 메소드를 생성할 수 있도록, In Place 원소 구조를 사용하는 것도 최적화 전략을 개선하는 하나의 방법입니다. In Place 원소 구조를 직상위 클래스 내에 있는 다이나믹 디스패치 VI 안에 놓고, In Place 원소 구조에 여러 쌍의 In Place 원소 노드를 놓습니다. 이러한 노드 쌍을 사용함으로써, 어떤 입력을 어떤 출력과 연결하고, 어떤 입력을 상수로 취급하고, 어떤 입력을 변경된 것으로 취급할 지 등을 LabVIEW에게 전달할 수 있습니다. 이를 통해 LabVIEW는 호출자 VI를 최적화할 수 있게 됩니다.

다이나믹 디스패치 터미널 사용 예제는 다음의 예제를 참조합니다.

  • labview\examples\Object-Oriented Programming\Dynamic Dispatching\Dynamic Dispatching.lvproj
  • labview\examples\Object-Oriented Programming\Dynamic Terminals\Dynamic Terminals.lvproj