안녕하세요. 이 프레젠테이션을 시청해 주셔서 감사합니다. JMP 클래스 몇 가지와 JSL에서 이 클래스를 사용하여 동적이고 확장 가능한 인터페이스 동작을 구현하는 방법에 대해 설명하겠습니다.
저는 벤 배럿입니다. IDEXX 연구소에서 일하고 있습니다. 10년 정도 엔지니어로 일해 왔습니다. LabVIEW, MATLAB 등 다양한 애플리케이션을 다루었고, C#도 사용해 봤습니다. 이 모든 언어에서 저는 항상 객체 지향 프로그래밍 방식을 선호했습니다.
왠지 모르게 직관적으로 느껴졌습니다. 하지만 JSL에서 객체를 다루기 시작하면서 그런 직관이 제게는 별로 도움이 되지 않는다는 것을 깨달았습니다. 극복해야 할 몇 가지 미묘한 차이점이 있었지만, 일단 사용법을 파악하고 나니 매우 유용하다는 것을 알게 되었습니다.
먼저 간략한 개요부터 말씀드리겠습니다. 여기서는 JMP 수업에 대한 심도 있는 강의를 진행하지 않겠습니다. JMP를 처음 접하면서 제가 발견한 과정을 간략하게 설명드리겠습니다. 제가 어려웠던 점, 겪었던 어려움, 그리고 어떻게 극복했는지, 그리고 마지막에는 제가 JMP를 어떻게 활용했는지에 대한 멋진 예시들을 소개합니다.
대략적인 계획은 다음과 같습니다. 얼마나 잘 지킬 수 있을지 지켜봐야겠습니다. 범위 지정에 대해서도 잠깐 이야기해 보겠습니다. 제가 일부 클래스를 구현하는 방식에서 스코핑이 지속적으로 문제가 되어 왔고, 이를 바탕으로 제가 찾아낸 모범 사례들을 소개할 예정입니다. 또한 JSL의 클래스가 C#과 같은 다른 언어에서 기대하는 것과 어떻게 다른지에 대해서도 이야기해 보겠습니다. 그런 다음 함수형 데모 코드를 살펴보겠습니다.
이 글에서 JSL 클래스에 대한 심도 있고 심도 있는 강의를 기대하지는 마세요. 심지어 객체 지향 설계 원칙에 대한 전반적인 내용도 기대하지 마세요. 이 글이 클래스에 대해 직접 파고들 때 골치 아픈 부분을 피하는 데 도움이 되기를 바랍니다.
일정은 다음과 같습니다. 모든 내용을 살펴보았습니다. JSL에서 사용 가능한 다양한 범위에 대한 간략한 개요는 다음과 같습니다. 이 모든 범위가 어떻게 상호 작용하는지, 그리고 어떻게 사용할 수 있는지 완전히 이해한다고는 할 수 없지만, 몇 가지 기본적인 아이디어는 있습니다.
네 가지 일반적인 범위가 있습니다. 여기에는 로컬 범위, 글로벌 범위, 그리고 사용자 지정 네임스페이스가 있습니다. 이 문서에서는 각 범위와 상호 작용하는 방법을 간략하게 설명했습니다. 더 자세한 정보를 원하시면 온라인 설명서를 참조하는 것을 강력히 권장합니다. 하지만 일반적으로 클래스를 다룰 때 제가 찾은 가장 좋은 방법은 네임스페이스를 활용하는 것입니다.
클래스에서 참조해야 하는 경우 사용자 지정 네임스페이스를 만들면 발생했던 범위 및 충돌 문제를 많이 피할 수 있었습니다. 또한 Here 네임스페이스는 클래스와 관련해서는 그다지 신뢰할 수 없다는 것을 알게 되었기 때문에, Here 네임스페이스를 기본값으로 지정하고 이를 기본값으로 설정하는 것은 피하려고 합니다. 또한, 로컬 Here 명령을 사용하지 않는 한 로컬 변수를 사용하는 것도 도움이 될 수 있습니다. 하지만 로컬 변수로 지정할 변수를 명시적으로 정의해야 하므로 유지 관리가 약간 더 까다롭습니다. 하지만 이 중 일부는 데모를 살펴보면 더 명확해질 것입니다.
방금 그 모범 사례들을 살펴보았습니다. 기본 이름을 사용하지 말고, 사용자 지정 네임스페이스를 사용하고, 클래스도 사용하세요. 클래스는 어떤 면에서 복사 가능한 네임스페이스라고 생각할 수 있으며, 동시에 메모리에 중복된 네임스페이스를 가질 수 있습니다. JSL 클래스는 여러분이 익숙한 클래스와 어떻게 다를까요? 클래스에서 기대하는 기능이 더 많을 수도 있겠지만, 이 다섯 가지 기능은 사람들이 객체에서 기대하는 기능을 상당히 표준적으로 표현한 것이라고 생각합니다.
캡슐화, 상속, 다형성, 복제, 그리고 추상화. 상속, 다형성, 그리고 추상화는 모두 서로 연관되어 있으며, JSL의 클래스는 캡슐화, 상속, 그리고 복제를 꽤 잘 지원하지만, 다형성 동작과 추상화를 구현하는 데에는 몇 가지 미묘한 차이가 있습니다. 이 다섯 가지에 대해 간략하게 설명하겠습니다.
캡슐화는 꽤 잘 지원됩니다. 클래스를 정의할 때 해당 클래스와 관련된 속성과 메서드를 정의합니다. 여기서 유일한 차이점은 이 중 어느 것도 사실이 아니라는 것입니다. 클래스의 진정한 private 멤버를 정의할 수 없습니다. 모든 것이 public입니다. 마치 네임스페이스와 같습니다. 클래스의 멤버와 속성에 대한 전역 접근 권한이 있습니다.
상속도 지원됩니다. 다른 클래스에서 파생된 클래스를 만들면 해당 자식 클래스는 부모 클래스의 멤버를 상속합니다. 다형성에는 몇 가지 미묘한 차이가 있는데, 나중에 더 자세히 살펴보겠습니다. 다형성을 제대로 구현하려면 부모 클래스가 자신의 메서드 내에서 자식 메서드로 적절하게 디스패치할 수 있도록 하는 구체적인 해결 방법이 필요합니다.
복제, 이것이 바로 클래스를 사용하는 핵심입니다. 객체의 여러 복사본을 인스턴스화할 수 있으며, 각 복사본은 자체적으로 캡슐화된 매개변수와 메서드 집합을 가지게 됩니다. 저는 이 부분에서 아무런 문제도 겪지 않았습니다.
추상화에 대해 이야기하자면, JSL 클래스에는 추상화라는 명확한 개념이 없지만, 오류를 반환하거나 기본적인 동작을 수행하는 기본 메서드가 있는 부모 클래스를 정의할 수 있습니다. C#이나 다른 언어에 익숙하다면 이는 추상 메서드보다는 가상 메서드에 더 가깝습니다. 지금까지 JSL의 클래스가 다른 언어에서 익숙한 클래스와 어떻게 다른지 간략하게 살펴보았습니다. JSL 클래스에 대한 간략한 개요를 바탕으로, 다음 내용으로 넘어가겠습니다.
JMP 인스턴스를 열었습니다. 꽤 간단한 예제가 몇 개 있습니다. 음, 간단한 예제 하나부터 시작해 보고, 그다음은 조금 더 복잡한 예제, 그리고 그다음은 훨씬 더 복잡한 예제입니다. 가장 먼저 설명드릴 것은 아주 기본적인 진행률 표시줄입니다.
이 데모들은 모두 GUI 개발을 더욱 확장 가능하고 모듈화하여 객체의 기능을 최대한 활용할 수 있도록 하는 맥락에서 작성되었습니다. 이 진행률 표시줄에서는 어떤 기능을 하는지 보여드리기 위해 아주 간략하게 실행해 보겠습니다. 진행률 표시줄의 기본 구현은 온라인 어딘가에 있는 게시물에서 찾았는데, 누군가 질문해서 이렇게 작성했습니다. 진행률 표시줄이 어떻게 만들어졌는지 자세히 보여드리겠지만, 여기서 가장 중요한 내용은 아닙니다.
이 코드는 기본적으로 진행률 표시줄의 모양을 정의하는 몇 가지 요소를 설정하는 것입니다. 창을 만들고, 객체를 만들고… 보시다시피 객체를 만들고 있고, 잠시 후에 객체에 대한 코드를 살펴보겠습니다. 그런 다음 창에 객체를 배열하고, 실행할 작업을 나타내는 임의의 요소를 만듭니다. 그런 다음 마치 어떤 처리를 하는 것처럼 반복하고, 클래스 정의 자체에 포함된 이러한 메서드를 사용하여 진행률 표시줄을 업데이트합니다.
여기에는 회전이 없지만, 이 객체는 이 시각화를 만드는 모든 동작을 캡슐화하고 있습니다. 해당 창을 불러오겠습니다. 지금 코드에 있습니다. 진행률 표시줄 클래스 정의로 가서 이 부분들을 빠르게 최소화해 보겠습니다. 보시다시피 클래스 정의는 define class 호출을 사용하여 클래스를 정의하고 이름을 지정하면 인스턴스화됩니다. 그런 다음 클래스에서 변수를 정의하는 것은 매우 간단합니다. 다른 변수를 정의하는 것과 같은 방식으로 변수를 정의하면 됩니다.
이제 이 값은 클래스 인스턴스에 할당되므로 클래스 참조를 통해 해당 이름을 지정하여 접근할 수 있습니다. 클래스의 메서드는 함수를 정의하는 것과 같은 방식으로 정의됩니다. 본질적으로 다른 이름을 가진 함수이며, 이 함수들은 해당 클래스 객체에 할당됩니다. 앞서 클래스가 네임스페이스와 같다고 말씀드렸듯이, 클래스의 인스턴스를 생성한 후에는 이러한 모든 것을 조작할 수 있습니다. 생성한 객체에 할당될 속성을 추가할 수 있습니다. JMP 클래스를 사용하여 매우 동적인 작업을 다양하게 수행할 수 있습니다.
이 부분에 대해서는 자세히 설명하지 않겠습니다. 진행률 표시줄이 어떻게 생성되는지에만 집중하겠습니다. 초기화 함수가 실행됩니다. 이 부분을 좀 더 자세히 살펴보겠습니다. 이 예제에서 초기화 함수는 객체를 생성할 때 실행됩니다. 새 객체를 호출하면 자동으로 _init이 실행됩니다.
초기화할 때 기본 구성이 여기에 설정되어 있지만, 원하는 구성을 직접 지정할 수도 있습니다. 이렇게 하면 모든 기본적인 사항이 설정되고, 마지막에 빌드 명령이 호출됩니다. 빌드 메서드는 여기에 정의되어 있습니다. 빌드 메서드에서 진행률 표시줄을 현재처럼 보이게 하는 모든 객체를 생성합니다. 컨테이너가 있고, 몇 개의 스페이서 상자가 있는데, 이 스페이서 상자를 늘리거나 줄여서 진행률 효과를 만들 수 있습니다. 다시 말하지만, 이 부분은 출처가 어디인지는 모르겠지만 JMP 커뮤니티 게시물에서 가져온 것입니다.
이렇게 하면 진행률 표시줄이 어떻게 보일지에 대한 모든 세부 정보가 설정됩니다. 여기에 높이나 너비를 변경하는 도우미 메서드가 있고, 이 메서드들을 모두 호출할 수 있습니다. 그리고 진행률 표시줄과 어떻게 상호작용하고 진행률을 변경할 수 있을까요? 이것들은 메서드일 뿐입니다. 각 메서드는 서로 다른 기능을 가지고 있는데, set 메서드는... 백분율을 명시적으로 특정 값으로 설정합니다. Step 메서드는 특정 양만큼 진행률을 조정하고, 그 외에 원하는 다른 속성들을 정의할 수 있습니다.
단계 수를 정확히 지정하고 반복할 때마다 단계 수를 증가시킬 수 있습니다. 특정 작업에 맞게 메서드를 원하는 대로 조정할 수 있습니다. 다시 한번, 맥락을 파악했으니 예제로 돌아가 보면, 이 작업은 매우 간단합니다. 객체를 생성하고… 여기서 새 창을 설정할 때 객체를 활용하려면 실제 디스플레이 요소를 가져와야 합니다.
진행률 표시줄에서 상위 컨테이너는 여기 H 목록 상자입니다. 하지만 객체를 가져오면 해당 값이나 컨테이너를 반환하는 것뿐입니다. 새 창 정의에서 특정 위치에 진행률 표시줄을 삽입하려면 해당 객체나 생성한 객체를 가져와서 가져오면 됩니다. 이는 get panel과 같은 방식으로 설명할 수 있습니다. 더 명확하겠지만, 여기 있습니다.
어쨌든, 이런 식으로 삽입하는 겁니다. 그리고 여기서도 여전히 객체 참조를 참조하고, 기본 막대에 대해서는 단계별로 실행하고, 보조 막대에는 명시적인 값으로 설정합니다. 여기서 텍스트를 업데이트합니다. 무슨 일이 일어나는지 확인하기 위해 한 번 더 확인합니다. 다시 말하지만, 무작위 값을 적용하고 업데이트하는 것뿐입니다. 이걸 다른 작업에 어떻게 삽입할 수 있을지 상상해 보세요.
제가 유용하다고 생각했던 또 다른 점은 진행률 표시줄을 닫을 수 있다는 것입니다. 그렇게 하면 다음에 반복 작업을 시도할 때 창에 대한 참조가 더 이상 없기 때문에 실패합니다. 진행률 표시줄을 닫았는데, 이제 이 업데이트를 실행하여 창을 업데이트하려고 하면 업데이트가 실패합니다. 그래서 오류가 반환됩니다.
이 모든 것이 try 문으로 감싸져 있기 때문에 실패하면 여기로 쫓겨나게 됩니다. 따라서 필요한 경우 처리를 중단하는 빠르고 간단한 방법입니다. 저는 여러 번 이런 작업을 했습니다. 이게 진행률 표시줄입니다. 아주 기본적인 구현이죠. 사용자 정의할 수 있는 방법은 여러 가지가 있습니다. 정보를 가져오는 등 원하는 대로 할 수 있습니다.
다음으로 제가 이야기하고 싶은 것은 좀 더 복잡하고, 아마도 약간의 설정이 필요할 것입니다.여기에 이 테이블들을 가져오고 싶습니다.가상 조인 기능을 보여주고 싶기 때문에 큰 클래스 샘플 테이블을 가져와서 무작위 데이터를 만들었습니다.가상 조인에 익숙하지 않은 사람들을 위해 표준 조인이 있는데, 여기서 우리는... 큰 점수의 클래스가 있습니다.모든 학생에 대한 여러 항목이 있습니다.그들은 무언가를 하기 위해 10번 시도했고, 점수를 받았습니다.그들의 이름, 시도, 점수만 있지만, 여기에는 다른 모든 정보가 있습니다.여기에 가져오고 싶습니다.조인을 수행합니다.JMP를 사용하는 사람이라면 누구나 이전에 이것을 해본 적이 있을 것입니다.
이렇게 하면 이 값들이 이 테이블에 반영되지만, 다른 방법도 있습니다. 이 이름들은 모두 고유합니다. 이 이름들을 링크 ID로 설정한 다음, 이 테이블에서 이 값을 가져와서 이 테이블을 참조할 수 있습니다. 이제 가상 조인을 통해 모든 정보를 볼 수 있습니다. 여기로 돌아오면 숨기거나 다시 표시할 수 있으며, 이제 조인을 하지 않고도 이 테이블의 이 열에 있는 정보에 접근할 수 있습니다. 이 테이블에도 같은 작업을 할 수 있습니다.
여기에는 꽤 멋진 장점이 있습니다. 열 정보와 링크 참조 속성으로 들어가면 선택됨 또는 제외됨 상태를 허용하도록 설정할 수 있습니다. 이 속성을 적용하고 여기로 와서 이 행을 선택하면 관련된 모든 행이 선택됩니다. 요약을 만들고 데이터 테이블이나 데이터 뷰에 링크를 추가하는 경우에도 같은 작업이 수행됩니다.
정말 멋진 기능입니다. 작년쯤부터 사용하기 시작했는데, JSL 스크립팅으로 자동화할 방법이 정말 필요해서 결국 링크 관리자를 어느 정도 작성하게 되었습니다. 이 부분들을 지워 보겠습니다. 링크 ID와 링크 참조를 지웁니다. 이제 링크가 없는 일반 테이블이 됩니다.
제가 할 일은 여기 링크 관리자 예제를 불러오는 것입니다. 이 중 일부를 실행해 보겠습니다. 모든 테이블을 설정하고 링크 관리자를 초기화할 것입니다. 이 모든 작업의 코드는 잠시 후에 살펴보겠습니다.
자, 이제 됐네요. 무슨 오류인지는 모르겠지만, 여기 링크 관리자 기본 창이 있습니다. GUI는 실행했지만 아직 아무것도 연결되지 않았습니다. 사용할 수 있는 API를 사용하면 링크 소스를 설정할 수 있는데, 이는 기본적으로 제가 이전에 링크 ID를 설정했던 것과 동일합니다. 실행하면 링크 관리자가 업데이트된 것을 확인할 수 있습니다.
여기에 새로운 GUI 항목이 있습니다. 이제 테이블 중 하나를 연결할 수 있습니다. 새 항목이 생성됩니다. 두 번째 테이블을 연결할 수 있습니다. 두 번째 항목이 생성되었고, 이제 이러한 연결 구성을 수정하고 수정할 수 있습니다.
이 디스패치를 원하고, 두 번째 테이블을 원하면, 선택 및 제외 항목이 모두... 기본적으로 여기서 무언가를 선택하면 여기로 전파되도록 설정할 수 있습니다. 원하는 항목을 선택했습니다. 이제 이 모든 항목을 선택하고, 원본 테이블에서 소스 테이블도 선택해야 합니다.
일반적으로 이러한 항목을 업데이트하려면 마우스 오른쪽 버튼을 클릭하고 열 정보로 이동한 후, 링크 참조로 이동하고, 디스패치 또는 수락으로 이동하여 원하는 항목을 변경한 다음 적용하고, 다른 항목으로 이동하여 작업을 수행해야 합니다. 저는 좀 더 역동적인 것을 원했고, 무슨 일이 일어나고 있는지 볼 수 있는 것을 원했습니다. 다른 테이블을 사용하거나, 이 모든 작업을 수행하도록 여러 소스를 설정할 수도 있고, 모든 구성이 여기에 있으므로 기능을 끄거나 링크를 제거하는 등 모든 작업을 수행할 수 있습니다.
이 도구는 여러 테이블에 걸쳐 있는 더 큰 데이터 세트를 다룰 때 특히 유용하다고 생각했습니다. 예를 들어 하나의 큰 요약 테이블이 있고, 연속형 데이터에 대한 데이터 처리를 수행한 후, 여러 데이터를 연결하고 싶지만 너무 큰 테이블을 만들면 다루기 힘들어질 수 있기 때문에 피하고 싶을 때 유용합니다. 이 도구는 바로 이러한 모든 상황에서 탄생했습니다.
이제 코드에 대해 자세히 살펴보겠습니다. 좀 더 복잡한 과정이 필요한데, 한 가지 분명히 말씀드리고 싶은 건 이 모든 것이 최적화되지 않았다는 겁니다. 아직 많은 부분이… 초안 구현이라고 할 수 있을 것 같습니다. 작동은 했지만, 아직 수정하지 않았습니다. 이 글들을 읽어가면서 이 점을 꼭 명심하세요.
제가 호출한 초기화 함수를 여기서 볼 수 있는데, 이 함수는 객체가 있는지 확인하는 역할만 하고, 없으면 객체를 생성합니다. 개선이 가능한 부분 중 하나는 원래 여러 프로젝트가 진행 중일 때 여러 링크 관리자가 동시에 활성화되는 것이 좋겠다는 생각에서 시작했는데, 유용할 수도 있고 그렇지 않을 수도 있지만, 이 클래스는 현재 기본적으로 싱글턴으로 구현되어 있습니다.
원한다면 더 많은 인스턴스를 생성할 수 있지만, 그 기능은 나중에 자세히 설명할 몇 가지 세부 사항에 대해서는 다소 모호할 수 있습니다. 하지만 기본적으로 링크 관리자는 테이블이 어떻게 연결되는지, 어떤 테이블이 무엇에 연결되는지, 그리고 링크의 현재 상태가 무엇인지 정의하는 배열을 관리하는 역할을 합니다. 링크를 변경하는 등 다양한 작업을 수행하는 메서드가 있습니다.
GUI용으로 구현한 클래스가 두 개 있습니다. 하나는 링크 구성입니다. 링크 관리자 창을 불러오겠습니다. 어디에 있나요? 바로 여기 있습니다.
링크 관리자 창을 살펴보면, 링크 구성은 수락 디스패치, 제외 선택 등을 변경할 수 있는 상자입니다. 이것이 구성이고, 탭은 링크 소스 탭입니다. 소스에는 탭이 있는데, 어떤 열을 연결할 수 있고, 어떤 열을 연결할 수 있는지 등 다양한 규칙이 있기 때문입니다. 링크 소스를 만들 때 링크 관리자는 이러한 객체 중 하나를 생성합니다.
테이블이 닫힐 때 등을 확인하기 위한 이벤트를 설정하고 확인하는 등 여러 가지 작업이 진행 중인데, 이 모든 작업은 무시해도 됩니다. 바로 여기가 핵심입니다. 새 링크 소스 탭 객체를 생성하고 테이블을 제공하는 것입니다.
거의 다 됐네요. GUI에 추가되는데, 아마 여기 아래 어딘가에 있을 겁니다. 여기에 소스 목록이 있고, 이 목록이 저 목록에 추가됩니다. 이건 그냥 컨테이너일 뿐인데, 실제 표시 객체인 탭을 가져오는 함수가 어디에 있는지 보이시죠? 이 함수가 기본적으로 복제의 많은 부분을 처리합니다. 새 소스를 만들 때마다 이 소스들을 새로 만들고 모든 기능을 자동으로 가져옵니다.
소스 탭으로 들어가면 초기화가 있습니다. 자체 표시 객체, 페이지 상자, 정렬 작업, 그리고 목록 객체가 있습니다. 이 객체에는 여러분이 가질 수 있는 모든 링크 구성이 포함되어 있습니다. 다시 한번 말씀드리지만, 최적화가 조금 덜 되었을 수 있지만, 조금씩 더 나아지고 있다는 것을 느끼실 수 있을 겁니다. JMP에서 인터페이스에 동적 동작을 구현하는 것이 잠재적으로 더 쉽습니다. 저는 이 방식을 다른 여러 곳에서 사용해 왔습니다.
여러분 중 일부는 제가 여기 이 리콜 라이브러리를 가지고 있다는 것을 눈치채셨을 겁니다. 제가 조금 전에 훨씬 더 복잡한 구현이 있다고 처음 언급했던 바로 그 라이브러리입니다. 이 부분에 대해 자세히 다룰 시간이 많지 않을 것 같습니다. 사실 이 프로젝트가 제가 JMP 클래스를 사용하여 착수한 첫 번째 프로젝트였기 때문에 시간이 있었으면 좋았을 텐데요. 아쉽게도 아직 초안 단계라고 할 수 있습니다. 여기에는 아주 쉽게 통합할 수 있는 부분이 많습니다.
이 시점에서는 JMP의 클래스를 활용하여 더욱 동적인 동작을 제공하고 코드를 좀 더 깔끔하게 만드는 방법에 대해 생각해 보셨으면 좋겠습니다. 예전에 제가… 복잡하고 동적인 UI 코드에서 모든 것을 새 창 함수에 직접 빌드하는 것을 본 적이 있거든요.
새 창에 탭 20개가 생기고, 이 모든 기능과 버튼이 이것저것 동작합니다. 하지만 훨씬 깔끔하고 객체 기반으로 동일한 동작을 구현하는 방법이 있습니다. 유지 관리, 확장성이 뛰어나고 가독성도 더 좋습니다. UI를 구현할 때 클래스를 사용하는 데는 많은 이점이 있다고 생각합니다.
리콜에 대한 내용은 다루지 않겠습니다. 다만, 이 모든 예제 코드와 리콜 라이브러리를 정리하여 공개 Git 저장소에 제공할 계획입니다. 관심 있는 분들은 누구나 살펴보고, 복제하고, 포크하고, 원하는 대로 활용하면서 JMP 클래스를 자신의 코드에 어떻게 적용하여 효율성을 높일 수 있는지 알아볼 수 있습니다.
이제 제가 범위 지정에 대해 처음에 이야기했던 몇 가지 사항을 간략하게 짚어보는 것만 남았습니다. 예제를 살펴보았고, 동적 GUI를 구현하기 위한 구조를 어떻게 구축할 수 있는지 알아보았습니다. 이제 골치 아픈 부분이 무엇인지, 그리고 어떻게 해결할 수 있는지 이해해야 합니다. 좋은 예시는 다음과 같습니다… 여기서 구현할 수 있는지 확인해 보겠습니다.
이 중 하나를 선택한다면, 앞서 말씀드린 범위 문제는 메서드 호출 방식과 메서드가 상속하는 범위와 관련이 있습니다. Here 네임스페이스에서 작업할 때 발생하는 여러 문제를 봤습니다. 전역 네임스페이스와 메서드 간의 충돌도 봤습니다. 최대한 간단하게 만들기 위해, 클래스에서 발생할 수 있는 범위 문제를 해결하는 가장 확실한 방법은 바로 로컬 수정자를 사용하는 것입니다. 여기서는 설명하지 않지만, 이 예시를 통해 어떤 방식으로 할 수 있는지 보여드리겠습니다. 저는 로컬 수정자를 다음과 같이 포맷하는 것을 좋아합니다.
여기서 명시적으로 정의해야 하는 유일한 변수는 이 변수입니다. 여기서 이 변수는 참조를 생성할 속성을 파싱하고 생성하기 위해 설정하는 변수일 뿐입니다. 이 코드는 중요하지 않습니다. 이 변수는 로컬로 정의되지 않았기 때문에 다른 범위의 변수를 가릴 수 있으며, 코드에서 이 메서드가 호출되는 위치에 따라 이 변수가 충돌을 일으킬 수 있습니다.
클래스와의 범위 충돌을 피하는 가장 깔끔한 방법은 지역 변수를 명시적으로 지정하는 것입니다. 이 글의 대부분은 제가 이러한 문제들을 해결하는 가장 좋은 방법이 무엇인지 이해하기 전에 작성되었기 때문에, 기본적으로 모든 메서드에 대해 이 작업을 수행해야 할 것으로 예상합니다. 이 문제를 해결하는 데 도움이 되는 또 다른 유일한 방법은 명시적인 네임스페이스 식별을 사용하는 것입니다.
라이브러리를 작성할 때마다 기본적으로 새로운 사용자 정의 네임스페이스에 작성하고, 모든 변수와 메서드 또는 변수와 함수를 해당 네임스페이스의 일부로 정의하려고 노력하는데, 이렇게 하면 충돌을 피하는 데 도움이 됩니다.
그리고 사실, 또 하나 이야기할 만한 게 있는데, 이건 좋은 예는 아니지만, 다형성과 상속의 몇 가지 문제점에 대한 이야기입니다. 어디 한번 볼까요. 이 주제에 대해 이야기하기 좋은 곳은 리콜 라이브러리가 아닐까 싶습니다.
바라건대, 너무… 구현의 세부 사항 중 일부는 생략하고 문제가 무엇인지에만 집중할 수 있습니다. 지금까지 살펴본 바에 따르면, 이 리콜 패널은 기본적으로 필드 값을 자동으로 리콜하도록 설정할 수 있는 컨테이너입니다. 이 패널은 상속되도록 설계되었으므로, 일부 동작을 호출해야 하는 자식 클래스가 있어야 합니다. 바로 이 메서드입니다. 자식 클래스는 자체 버전의 빌드 메서드를 구현해야 합니다.
이제 다형성의 미묘한 차이가 작용하는 부분입니다. 다른 메서드 중 하나에서 이 메서드를 호출하려고 하면, 즉 부모 클래스에 있고 build를 호출하려고 하는데 빌드를 재정의하는 자식 클래스가 있는 경우, 자식 메서드에 build가 제대로 전달되지 않기 때문입니다. 백엔드에서 클래스가 구현되는 방식에 미묘한 차이가 있는 이유에 대한 설명은 없습니다. 하지만 이를 우회할 방법이 있습니다. 다른 라이브러리에서 가장 잘 설명될 것 같지만, 아쉽게도 저는 그 부분에 대해서는 자세히 설명할 준비가 되어 있지 않습니다.
그 부분에 대한 자세한 설명은 피하고, 다형성, 즉 동작을 재정의하는 자식 클래스를 구현할 수 있다는 사실이 예상대로 작동하지 않을 수도 있다는 말로 마무리하겠습니다. 상속이 클래스의 가장 유용한 측면 중 하나라고 생각하기 때문에 이는 약간 안타까운 일입니다.
동작을 상속할 수는 있지만, 부모 클래스에서 상속된 동작을 호출하는 것은 조금 더 복잡합니다. 저는 그렇게 표현하려고 합니다. 이 자료를 온라인에 게시할 때, 어떻게 그리고 왜 그렇게 할 수 없는지에 대한 구체적인 예를 몇 가지 포함하도록 하겠습니다. 다시 말하지만, 저는 Junk JSL에서 UI 디자인에 클래스를 통합하는 방법에 대한 개요만 제공하려고 합니다.
그러니까, 너무 장황하게 늘어놓으려는 건 그만하고요. 다시 한번 말씀드리지만, 제 이름은 벤 배럿입니다. 궁금한 점이 있거나 이 구현 사례들을 더 보고 싶으시면 언제든지 연락 주세요. 그 외에도 정말 감사합니다.