JavaRush /Java Blog /Random-KO /현상으로서의 상속
articles
레벨 15

현상으로서의 상속

Random-KO 그룹에 게시되었습니다
사실을 말씀드리자면 저는 이 글을 처음부터 기획한 것은 아닙니다. 나는 여기서 논의하고 싶은 문제를 언급할 가치조차 없는 사소한 문제로 생각했습니다. 하지만 이 사이트에 글을 쓰는 과정에서 저는 한 포럼에서 다중 상속에 대한 논의를 제기했습니다. 그 결과, 대부분의 개발자들은 상속에 대해 매우 막연하게 이해하고 있는 것으로 나타났습니다. 따라서 그는 많은 실수를 저지릅니다. 상속은 OOP의 가장 중요한 기능 중 하나이기 때문에(가장 중요하지는 않더라도!) 이 현상에 대해 별도의 기사를 쓰기로 결정했습니다. * * * 먼저 객체와 클래스라는 두 가지 개념을 구별하고 싶습니다. 이러한 개념은 끊임없이 혼란스러워집니다. 한편, 이들은 OOP의 핵심입니다. 그리고 제 생각에는 그들 사이의 차이점을 아는 것이 필요합니다. 그래서, 물체. 기본적으로 그것은 무엇이든 됩니다. 여기 큐브가 있습니다. 나무, 파란색. 가장자리의 길이는 5cm이며 이것은 물체입니다. 그리고 피라미드도 있어요. 플라스틱, 빨간색. 갈비뼈 10cm. 이것도 객체입니다. 그들의 공통점이 무엇입니까? 다른 크기. 다른 모양. 다른 재료. 그러나 공통점이 있습니다. 우선, 정육면체와 피라미드는 모두 정다면체이다. 저것들. 꼭지점 수와 면 수의 합이 모서리 수보다 2개 더 많습니다. 더 나아가. 두 모양 모두 면, 모서리 및 꼭지점을 가지고 있습니다. 두 수치 모두 갈비뼈 크기와 같은 특징을 가지고 있습니다. 두 모양 모두 회전할 수 있습니다. 두 그림 모두 그릴 수 있습니다. 마지막 두 속성은 이미 동작입니다. 등등. 프로그래밍 실습을 통해 이종 개체보다 동종 개체를 사용하는 것이 훨씬 쉽다는 것을 알 수 있습니다. 그리고 이 인물들 사이에는 여전히 공통점이 있기 때문에 어떻게든 이 공통점을 부각시키고 싶은 욕구가 있습니다. 여기서 클래스 개념이 등장합니다. 그래서 정의.
클래스는 개체 그룹의 공통 속성에 대한 설명입니다. 이러한 속성은 개체의 특성(크기, 무게, 색상 등)일 수도 있고 동작, 역할 등일 수도 있습니다.
논평. "all"(모든 속성에 대한 설명)이라는 단어는 사용되지 않았습니다. 이는 모든 객체가 여러 다른 클래스에 속할 수 있음을 의미합니다. 현상으로서의 상속 - 1 기하학적 모양을 기본으로 동일한 예를 들어보겠습니다. 가장 일반적인 설명은 정다면체 입니다 . 모서리 크기, 면 및 꼭지점 수에 관계없이. 우리가 아는 유일한 것은 이 도형에 꼭지점, 모서리, 면이 있고 모서리의 길이가 동일하다는 것입니다. 더 나아가. 설명을 좀 더 구체적으로 만들 수 있습니다. 우리가 이 다면체를 그리고 싶다고 가정해 봅시다 . 그려진 정다면체 와 같은 개념을 소개하겠습니다 . 그림을 그리려면 무엇이 필요합니까? 특정 꼭지점 좌표에 의존하지 않는 일반적인 그리기 방법에 대한 설명입니다. 아마도 물체의 색상일 것입니다. 이제 CubeTetrahedron 클래스를 소개하겠습니다 . 이 클래스에 속하는 객체는 확실히 정다면체입니다. 유일한 차이점은 각 새 클래스에 대해 꼭지점, 모서리 및 면의 수가 이미 엄격하게 고정되어 있다는 것입니다. 또한 특정 도형의 유형을 알면 그리는 방법에 대한 설명을 제공할 수 있습니다. 이는 Cube 또는 Tetrahedron 클래스의 모든 객체가 그려진 정다면체 클래스 의 객체이기도 함을 의미합니다 . 클래스의 계층 구조가 있습니다. 이 계층 구조에서는 가장 일반적인 설명부터 가장 구체적인 설명까지 내려갑니다. 모든 클래스의 개체는 계층 구조의 보다 일반적인 클래스에 대한 설명에도 적합합니다. 이 클래스 관계를 상속 이라고 합니다 . 각 하위 클래스는 상위 클래스의 모든 속성, 보다 일반적인 속성을 상속하고 (아마도) 이러한 속성에 자신의 일부 속성을 추가합니다. 또는 상위 클래스의 일부 속성을 재정의합니다. 여기에서는 객체지향 디자인에 관한 Gradi Bucha의 고전 책을 인용하고 싶습니다.
따라서 상속은 하위 클래스가 하나 이상의 상위 클래스에서 상속되는 클래스 간의 "is a" 계층 구조를 정의합니다. 이것은 실제로 유전에 대한 리트머스 테스트입니다. 클래스 A와 B가 주어졌을 때 A가 B의 종류가 "아닌" 경우 A는 B의 하위 클래스가 되어서는 안 됩니다.
번역하면 다음과 같습니다.
따라서 상속은 하위 클래스가 하나 이상의 상위 클래스에서 상속되는 클래스 간의 "is" 계층 구조를 정의합니다. 사실 이것은 상속을 정의하는 테스트(문자 그대로 리트머스 테스트, 내 노트)입니다. 클래스 A와 B가 있고 클래스 A가 클래스 B의 변형이 "아닌" 경우 A는 B의 하위 클래스가 아니어야 합니다.
여기까지 읽으신 분들은 아마도 어리둥절하여 관자놀이를 손가락으로 빙빙 돌리실 것입니다. 첫 번째 생각은 이것이 사소한 일이라는 것입니다! 이것은 사실이다. 하지만 내가 본 미친 상속 계층이 얼마나 많은지 안다면! 제가 맨 처음에 언급한 토론에서 참가자 중 한 명이 탱크를 기관총으로부터 물려받았습니다!!! 탱크에 기관총이 있다는 단순한 이유 때문입니다. 그리고 이것은 가장 흔한 실수입니다. 상속은 한 개체를 다른 개체 내에 포함하는 집계와 혼동됩니다. 탱크는 기관총이 아니며 기관총이 포함되어 있습니다. 그리고 이 오류로 인해 다중 상속을 사용하려는 경우가 가장 많습니다. 이제 Java로 직접 이동해 보겠습니다. 상속 측면에서 무엇이 있습니까? 언어에는 두 가지 유형의 클래스가 있습니다. 구현을 포함할 수 있는 클래스와 그렇지 않은 클래스입니다. 후자를 인터페이스라고 부르지만 본질적으로 완전히 추상 클래스입니다. 현상으로서의 상속 - 2 따라서 언어를 사용하면 잠재적으로 구현이 포함된 다른 클래스에서 클래스를 상속할 수 있습니다. 그러나 단 하나에서만 가능합니다! 왜 이런 일이 일어났는지 설명하겠습니다. 요점은 각 구현이 자신이 알고 있는 변수와 메소드를 사용하여 해당 부분만 처리할 수 있다는 것입니다. 그리고 AB 에서 클래스 C를 상속하더라도 클래스 A에서 상속된 processA 메서드는 내부 변수 a 에서만 작동할 수 있습니다. 왜냐하면 c 와 processC 메서드 에 대해 아무것도 모르듯이 b 에 대해 아무것도 모르기 때문입니다 . 마찬가지로 processB 방법 변수 b에서만 작동할 수 있습니다. 즉, 본질적으로 상속받은 부분이 분리되어 있는 것입니다. 클래스 C는 확실히 이들과 함께 작동할 수 있지만 상속되지 않고 단순히 일부로 포함되는 경우 이러한 부분과도 잘 작동할 수 있습니다. 그러나 여기에는 또 다른 골칫거리가 있는데, 이름이 중복된다는 점이다. processAprocessB 메소드의 이름이 동일하다면(예: process) 클래스 C 의 process 메소드를 호출하면 어떤 효과가 있습니까 ? 두 가지 방법 중 어느 것이 호출됩니까? 물론 C++에는 이러한 상황을 제어할 수 있는 기능이 있지만 이것이 언어에 조화를 더해주지는 않습니다. 따라서 구현 상속은 장점을 제공하지 않지만 단점이 있습니다. 이러한 이유로 Java의 구현 상속은 중단되었습니다. 그러나 개발자에게는 인터페이스로부터의 상속과 같은 다중 상속 옵션이 남아 있었습니다. Java 용어로 인터페이스 구현입니다. 인터페이스는 무엇입니까? 일련의 메소드. (우리는 현재 인터페이스의 상수 정의를 고려하고 있지 않습니다. 이에 대한 자세한 내용은 여기에서 확인하세요.) 메서드란 무엇인가요? 그리고 메소드의 핵심은 객체의 동작을 결정합니다. 거의 모든 메소드의 이름에 getXXX , drawXXX , countXXX 등 의 액션이 포함되어 있는 것은 우연이 아닙니다. 그리고 인터페이스는 메소드의 모음이므로 실제로 인터페이스는 동작을 결정하는 요소 입니다 . 인터페이스를 사용하는 또 다른 옵션은 객체의 역할을 정의하는 것입니다. 관찰자, 청취자 등 이 경우 방법은 실제로 일부 외부 이벤트에 대한 반응의 구현입니다. 그것은 다시 행동입니다. 물론 객체는 여러 가지 다른 동작을 가질 수 있습니다. 렌더링이 필요한 경우 렌더링됩니다. 구원받을 필요가 있다면 구원받은 것입니다. 글쎄요. 따라서 동작을 정의하는 클래스에서 상속하는 기능은 매우 유용합니다. 마찬가지로, 객체는 여러 가지 다른 역할을 가질 수 있습니다. 그러나 구현 행동은 전적으로 어린이 학급의 양심에 달려 있습니다. 인터페이스(구현)로부터의 상속은 이 클래스의 객체가 이런저런 일을 할 수 있어야 한다는 것을 의미합니다. 그리고 이를 수행하는 방법은 인터페이스를 구현하는 각 클래스에 의해 독립적으로 결정됩니다. 상속의 오류로 돌아가 보겠습니다. 다양한 시스템을 개발한 경험에 따르면 인터페이스에서 상속을 받으면 다중 구현 상속을 사용하지 않고도 모든 시스템을 구현할 수 있습니다. 따라서 C++에 존재하는 형태의 다중 상속이 부족하다는 불만 사항을 접할 때 이는 잘못된 설계의 확실한 신호입니다. 가장 흔한 실수는 제가 이미 언급한 것입니다. 상속은 집계와 혼동됩니다. 때로는 잘못된 가정으로 인해 이런 일이 발생합니다. 저것들. 예를 들어 속도계를 예로 들면, 속도는 거리와 시간을 측정해야만 측정할 수 있으며, 그 후에는 속도계가 눈금자와 시계로부터 성공적으로 상속되어 다음의 정의에 따라 눈금자와 시계가 된다고 주장됩니다. 계승. (속도계로 시간을 측정해 달라는 나의 요청은 대개 농담으로 대답되거나 전혀 대답하지 않았습니다.) 여기서 실수는 무엇입니까? 전제에서. 사실 속도계는 시간을 측정하지 않습니다. 그런데 거리도 마찬가지입니다. 모든 속도계에 있는 주행 기록계는 동일한 하우징에 있는 두 번째 장치의 전형적인 예입니다. 집합. 속도를 측정할 필요는 없습니다. 완전히 제거할 수 있습니다. 이는 속도 측정에 어떤 영향도 미치지 않습니다. 때로는 그러한 실수가 의도적으로 이루어지기도 합니다. 이것은 훨씬 더 나쁩니다. “네, 그게 잘못된 건 알지만 그게 나한테는 더 편해요.” 이것이 무엇으로 이어질 수 있습니까? 하지만 여기에 내용이 있습니다. 우리는 대포와 기관총에서 탱크를 물려받을 것입니다. 이 방법이 더 편리합니다. 결과적으로 탱크는 대포와 기관총으로 변합니다. 다음으로 비행기에 기관총 2개와 대포 1개를 장착하겠습니다. 우리는 무엇을 얻나요? 세 개의 탱크 형태에 무기가 매달린 항공기! 왜냐하면 그것을 이해하지 못한 채 탱크를 기관총으로 사용하는 사람이 분명히 있기 때문입니다. 상속 계층 구조에 따라 독점적으로 사용됩니다. 그리고 그는 절대적으로 옳을 것입니다. 왜냐하면 그러한 계층 구조를 설계한 사람이 실수를 했기 때문입니다.
일반적으로 저는 " 이렇게 하는 것이 나에게 더 편리하다" 는 접근 방식을 잘 이해하지 못합니다 . 듣는 사람처럼 쓰는 게 편하고, 기본적인 문법을 말하는 사람은 까칠하다. 물론 과장하고 있지만 주요 아이디어는 남아 있습니다. 순간적인 편리함 외에도 문해력과 같은 것이 있습니다. 이 개념은 수많은 사람들의 경험을 바탕으로 정의되었습니다. 실제로 이것이 영어로 "모범 사례"라고 불리는 최고의 솔루션입니다. 그리고 단순해 보이는 솔루션이 미래에 많은 문제를 가져오는 경우가 많습니다.
물론 이 예는 크게 과장되어 있어 터무니없다. 그러나 그럼에도 불구하고 치명적인 결과를 초래하는 덜 분명한 사례도 있습니다. 개체를 집계하는 대신 개체에서 상속함으로써 개발자는 누구에게나 상위 개체의 기능을 직접 사용할 수 있는 기능을 제공합니다. 그것이 의미하는 모든 것. 데이터베이스와 함께 작동하는 DBManager 클래스가 있다고 상상해 보세요 . DBManager - DataManager를 사용하여 데이터를 처리할 다른 클래스를 만듭니다 . 이 클래스는 데이터 제어, 변환, 추가 작업 등을 수행합니다. 일반적으로 비즈니스 계층과 기본 계층 사이에 있는 계층입니다. DBManager에서 DataManager를 상속하면 이를 사용하는 사람은 누구나 데이터베이스에 직접 액세스할 수 있습니다. 따라서 그는 제어, 변환 등을 우회하는 모든 작업을 수행할 수 있습니다. 좋습니다. 아무도 의도적인 해를 끼치고 싶지 않으며 직접적인 조치가 유능하다고 가정해 보겠습니다. 하지만! 베이스가 바뀌었다고 가정해보자. 내 말은, 통제나 변형의 일부 원칙이 바뀌었다는 뜻입니다. DataManager가 변경되었습니다. 그러나 이전에 데이터베이스와 직접 작업했던 코드는 계속 작동합니다. 그들은 아마도 그를 기억하지 못할 것입니다. 그 결과는 그것을 찾는 자들이 회색으로 변할 정도로 그런 부류의 오류가 될 것이다. DataManager를 우회하여 데이터베이스로 작업하는 일은 누구에게도 일어나지 않습니다. 그건 그렇고, 실제 생활의 예입니다. 오류를 찾는 데 매우 오랜 시간이 걸렸습니다. 마지막으로 다시 말씀드리겠습니다. 상속은 "is" 관계가 있는 경우에만 사용해야 합니다. 이것이 바로 상속의 본질이기 때문입니다. 즉 하위 클래스의 객체를 기본 클래스의 객체로 사용하는 능력입니다. 클래스 사이에 "is" 관계가 없다면 상속이 있어서는 안 됩니다!!! 어떤 상황에서도 절대로. 더욱이 – 너무 편리하기 때문입니다. 원본 소스 링크: http://www.skipy.ru/philosophy/inheritance.html
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION