문제

함수를 함수에 넣음으로써, 그 자체만으로는 캡슐화의 예를 구성합니까, 아니면 캡슐화를 위해 객체를 사용해야합니까?

캡슐화의 개념을 이해하려고 노력하고 있습니다. 내가 생각했던 것은 다음과 같은 것에서 가면 :

n = n + 1

이것은 큰 코드의 일부로 야생에서 실행 된 다음 그것을 취한 다음이를 이와 같은 함수에 넣은 다음 메소드에서 해당 추가 논리를 캡슐화했습니다.

addOne(n)
    n = n + 1
    return n

아니면 외부 세계에서 Addone의 세부 사항을 숨기는 경우에만 캡슐화되는 경우가 더 많아지고 있습니다. 객체 방법이었고 개인/보호의 액세스 수정자를 사용하는 것처럼?

도움이 되었습니까?

해결책

아마도 당신은 캡슐화와의 추상화를 혼란스럽게하고 있으며, 이는 객체 방향의 더 넓은 맥락에서 이해됩니다.

캡슐화는 다음 세 가지를 모두 포함합니다.

  • 추출
  • 구현 숨기기
  • 책임의 분열

추상화는 캡슐화의 한 구성 요소 일뿐입니다. 당신의 예에서 당신은 한 번 거주 한 코드의 본문에서 기능 추가를 추상화했습니다. 코드에서 어떤 공통점을 식별함으로써 - 특정 사례에 대한 개념 (추가)을 인식 (addect) (변수 n에 1 위를 추가). 이 능력으로 인해 추상화는 캡슐화 된 구성 요소 (메소드 또는 객체 - 재사용 가능합니다.

캡슐화 개념에 마찬가지로 중요한 것은 구현 숨기는 아이디어입니다. 이것이 캡슐화가 물체 방향의 경기장에서 논의되는 이유입니다. 구현 숨기기는 사용자로부터 객체를 보호하고 그 반대도 마찬가지입니다. OO에서는 객체의 사용자에게 공개 메소드 인터페이스를 제시하여이를 수행하는 반면, 객체의 구현은 개인 메소드 내부에서 발생합니다.

이것은 두 가지 이점을 제공합니다. 먼저, 객체에 대한 액세스를 제한함으로써 객체 사용자가 객체를 잘못된 상태로 남겨 둘 수있는 상황을 피합니다. 둘째, 사용자의 관점에서, 객체를 사용할 때는 느슨하게 결합됩니다. 나중에 구현을 변경하면 영향을받지 않습니다.

마지막으로, 책임의 분할 - OO 디자인의 광범위한 맥락에서 캡슐화를 올바르게 해결하기 위해 고려해야 할 것입니다. 임의의 함수 모음을 캡슐화하는 것은 사용하지 않습니다. 가능한 한 겹치거나 모호성이 거의 없도록 책임을 깨끗하고 논리적으로 정의해야합니다. 예를 들어, 화장실 대상이있는 경우 부엌 대상에서 책임 영역을 제거하고 싶을 것입니다.

그러나 제한된 의미에서, 당신은 함수를 추상화하여 일부 기능을 '모듈화'한다고 가정 해 봅시다. 그러나 내가 말했듯이, 용어로서 '캡슐화'는 객체 방향의 더 넓은 맥락에서 위에 나열된 세 가지 기준을 충족시키는 모듈화 형태에 적용되도록 이해된다.

다른 팁

나는 답변 트렌드 인 것 같다. 예, 함수는 어느 정도의 구현을 캡슐화합니다. 당신은 객체가 필요하지 않습니다 (클래스를 의미하는 데 사용한다고 생각합니다).

보다 메이어스 도.

당연히 그렇지.

예를 들어, 매개 변수에서만 작동하는 방법은 글로벌 정적 데이터에서 작동하는 방법보다 "캡슐화 된"것으로 간주됩니다.

캡슐화는 OOP보다 오래 전부터왔다 :)

방법은 자동차가 좋은 운전의 예입니다. 캡슐화는 Synax에 관한 것이 아니라 논리적 디자인 문제입니다. 물체와 방법 모두 양호하고 나쁜 캡슐화를 나타낼 수 있습니다.

그것에 대해 가장 간단한 생각은 코드가 구현에 대해 알거나 신경을 쓸 필요가없는 코드의 다른 부분의 세부 사항을 숨기거나 초록하는지 여부입니다.

차량으로 돌아 가기 예 : 자동 변속기는 양호한 캡슐화를 제공합니다. 수동 변속기는 나쁜 캡슐화입니다. 운전자의 관점에서 볼 때 저속/고속에 필요한 특정 기어는 일반적으로 운전자의 의도와 관련이 없습니다.

아니요, 객체는 아닙니다 필수의 캡슐화를 위해. 가장 광범위한 의미에서 "캡슐화"는 단지 "시야에서 세부 사항을 숨기는 것"을 의미하며 그와 관련하여 방법은 구현 세부 사항을 캡슐화하고 있습니다.

그렇다고해서 코드를 방법으로 나누었 기 때문에 코드가 잘 설계되었다고 말할 수는 없습니다. 500 개의 공개 방법으로 구성된 프로그램은 하나의 1000 라인 방법으로 구현 된 동일한 프로그램보다 훨씬 낫지 않습니다.

객체 지향 기술을 사용하는지 여부에 관계없이 프로그램 구축에서 여러 곳에서 캡슐화에 대해 생각해야합니다. , 모듈에 대한 인터페이스를 단순화하는 등

업데이트: 업데이트 된 질문에 답하기 위해 "메소드에 코드를 넣는 것"과 "액세스 수정 자 사용"은 논리를 캡슐화하는 다른 방법이지만 각각은 다른 수준에서 작용합니다.

방법에 코드를 넣으면 발신자가 해당 라인이 무엇인지 신경 쓰지 않도록 해당 방법을 구성하는 개별 코드 라인을 숨 깁니다. 그들은 방법의 서명에 대해서만 걱정합니다.

클래스의 메소드를 "개인"으로 표시하면 해당 방법을 숨겨서 소비자가 수업 그것에 대해 걱정할 필요가 없습니다. 그들은 수업의 공개 방법 (또는 속성)에 대해서만 걱정합니다.

구성 요소 수준입니다

확인하다 이것 밖으로:

컴퓨터 과학에서 캡슐화는 정의 된 인터페이스 뒤에있는 소프트웨어 구성 요소의 내부 메커니즘과 데이터 구조를 숨기는 것입니다. 이와 같은 방식으로 구성 요소 (다른 소프트웨어)의 사용자가 구성 요소가 수행하는 작업만을 알 수 없으며 그것이 어떻게하는지에 대한 세부 사항에 의존하게 만드십시오. 목적은 변화의 잠재력을 달성하는 것입니다. 구성 요소의 내부 메커니즘은 다른 구성 요소에 영향을 미치지 않으면 서 개선 될 수 있거나 구성 요소를 동일한 공개 인터페이스를 지원하는 다른 구성으로 대체 할 수 있습니다.

(나는 당신의 질문을 잘 이해하지 못합니다. 그 링크가 당신의 의심을 다루지 않으면 알려주세요)

캡슐화의 추상 개념은 구현 세부 정보를 숨 깁니다. 객체 지향은 ecnapsulation의 사용의 한 예일뿐입니다. 또 다른 예는 구현 모듈 및 정의 모듈을 사용하는 (또는 중고) Module-2라는 언어입니다. 정의 모듈은 실제 구현을 숨기고 캡슐화를 제공했습니다.

캡슐화는 블랙 박스를 고려할 때 사용됩니다. 물체는 블랙 박스입니다. 당신은 그들이 제공하는 방법을 알고 있지만 구현 방법은 아닙니다.

편집] 업데이트 된 질문의 예제 : 캡슐화를 얼마나 좁거나 넓게 정의하는지에 따라 다릅니다. 당신의 addone 예제는 내가 믿는 것을 숨기지 않습니다. 변수가 배열 인덱스 인 경우 정보 숨기기/캡슐화가되며 메소드 MOVENEXT를 호출하고 다른 기능 setValue 및 getValue가있을 수 있습니다. 이를 통해 사람들 (어쩌면 다른 기능과 함께)이 구조를 탐색하고 배열을 사용하여 자신과 함께 변수를 얻을 수 있습니다. 프로그래밍 언어가 다른 또는 더 풍부한 개념을 지원하는 경우 의미와 인터페이스를 변경하여 movenext, setValue 및 getValue의 구현을 변경할 수 있습니다. 나에게 그것은 캡슐화입니다.

비유로 이것을 다소 단순화합시다 : 당신은 자동차의 열쇠를 돌리고 시작합니다. 열쇠보다 더 많은 것이 있다는 것을 알고 있지만 가지다 아는 것 무엇 거기에서 계속되고 있습니다. Key Turn = 모터 시작. 키의 인터페이스 (즉, 함수 호출)는 엔진을 회전시키는 스타터 모터의 구현 등 (구현)을 숨 깁니다. 그게 캡슐화. 당신은 후드 아래에서 무슨 일이 일어나고 있는지 아는 것이 아끼지 않으며, 당신은 그것에 대해 행복합니다.

인공적인 손을 만든다면, 당신을 위해 열쇠를 돌리기 위해 ~ 아니다 캡슐화. 당신은 아무것도 숨기지 않고 추가 중개인 cruft로 키를 돌리고 있습니다. 그것이 당신의 예제가 나에게 상기시키는 것입니다. - 기능 호출을 통해 달성 되더라도 구현 세부 사항을 캡슐화하지 않습니다. 이 예에서는 코드를 선택하는 사람이라면 누구나 감사하지 않습니다. 실제로 그들은 인공적인 손으로 당신을 클럽 할 가능성이 더 높습니다.

정보 (클래스, 기능, 동적 라이브러리, 매크로)를 숨기려는 모든 방법을 캡슐화에 사용할 수 있습니다.

캡슐화는 단일 엔터티로 결합 된 객체의 속성 (데이터 멤버) 및 동작 (멤버 함수)이 클래스라고하는 프로세스입니다.

공개 분산 처리의 참조 모델 - 국제 표준화기구가 작성한 다음 개념을 정의합니다.

엔티티 : 모든 콘크리트 또는 추상적 인 관심사.

대상 : 엔티티의 모델. 물체는 그 행동과 이중 상태로 특징 지어집니다.

동작 (대상) : 언제 발생할 수 있는지에 대한 일련의 제약이있는 동작 모음.

인터페이스 : 해당 객체의 상호 작용의 하위 집합이 발생할 수있는 시점에 대한 일련의 제약 조건으로 구성된 객체의 동작의 추상화.

캡슐화 : 객체에 포함 된 정보가 객체가 지원하는 인터페이스의 상호 작용을 통해서만 액세스 할 수 있습니다.

이것들은 매우 넓습니다. 그러나 함수 내에 기능을 배치하는 것이 논리적으로 본 용어의 캡슐화를 구성하는 것으로 간주 될 수 있는지 여부를 확인합시다.

첫째, 함수는 분명히 '관심있는 것'의 모델입니다. 그것은 당신이 원하는 (아마도)가 원하는 알고리즘을 나타내며 알고리즘은 당신이 해결하려는 몇 가지 문제와 관련이 있다는 것입니다 (따라서 모델입니다). .

함수에 동작이 있습니까? 확실히 : 여기에는 실행하기 전에 함수가 어딘가에서 호출되어야한다는 제약 조건 하에서 실행되는 조치 모음 (모든 실행 파일 문일 수 있음)이 포함되어 있습니다. 인과 적 요인없이 기능을 언제든지 자발적으로 호출하지 않을 수 있습니다. 법률자처럼 들리나요? 당신은 betcha. 그럼에도 불구하고 쟁기질을합시다.

함수에 인터페이스가 있습니까? 확실히 그렇습니다 : 그것은 공식 매개 변수의 이름과 모음을 가지고 있으며, 그 결과 함수에 포함 된 실행 파일 문에 대한 맵 맵은 함수가 호출되면 이름과 매개 변수 목록은 실행 파일의 컬렉션을 고유하게 식별하도록 이해됩니다. 전화 당사자가 실제 진술을 지정하지 않고 실행 될 진술.

함수는 함수에 포함 된 정보가 객체가 지원하는 인터페이스에서의 상호 작용을 통해서만 액세스 할 수있는 속성을 가지고 있습니까? 음, 할 수 있습니다.

일부 정보는 인터페이스를 통해 액세스 할 수 있으므로 일부 정보는 함수 내에서 숨겨져 접근 할 수 없어야합니다. (그러한 정보 전시회는 정보 숨기기라고하며, 이는 모듈이 변경 될 가능성이있는 어려운 결정과 결정을 숨기도록 모듈을 설계해야한다고 주장함으로써 정의된다.) 따라서 함수 내에 어떤 정보가 숨겨져 있습니까?

이것을 보려면 먼저 척도를 고려해야합니다. 예를 들어, Java 클래스는 패키지 내에서 캡슐화 될 수 있다고 주장하기 쉽습니다. 일부 클래스는 공개적이며 (따라서 패키지의 인터페이스가 될 것입니다) 일부는 패키지-프라이버시 (따라서 패키지 내에서 정보가 숨겨져 있음)입니다. . 캡슐화 이론에서, 클래스는 노드를 형성하고 패키지는 캡슐화 된 영역을 형성하며, 전체는 캡슐화 된 그래프를 형성한다. 클래스 및 패키지의 그래프를 세 번째 그래프라고합니다.

또한 기능 (또는 방법) 자체가 클래스 내에서 캡슐화된다고 주장하는 것도 쉽습니다. 다시 말하지만, 일부 기능은 공개적이며 (따라서 클래스의 인터페이스의 일부가 될 것입니다) 일부 기능은 비공개 (따라서 클래스 내에서 정보가 숨겨져 있음)입니다. 함수 및 클래스의 그래프를 두 번째 그래프라고합니다.

이제 우리는 기능을 시작합니다. 함수가 자체 캡슐화의 수단이 되려면 다른 기능에 대한 정보와 기능 내에서 정보가 숨겨져있는 정보를 공개해야합니다. 이 정보는 무엇 일 수 있습니까?

McCabe에 의해 한 명의 후보자가 우리에게 제공됩니다. Cyclomatic Complexity에 관한 그의 획기적인 논문에서 Thomas McCabe는 소스 코드를 설명합니다. 여기서 '그래프의 각 노드는 흐름이 순차적이고 Arc가 프로그램에서 취한 분기에 해당하는 프로그램의 코드 블록에 해당합니다.'

함수 내에서 캡슐화 될 수있는 정보 단위로서 순차적 실행의 McCabian 블록을 취합시다. 함수 내의 첫 번째 블록이 항상 실행될 최초의 유일한 보장 블록이므로, 첫 번째 블록은 다른 함수에 의해 호출 될 수 있다는 점에서 첫 번째 블록이 공개되는 것으로 간주 할 수 있습니다. 그러나 함수 내의 다른 모든 블록은 다른 함수에 의해 호출 될 수 없으며 (중간 흐름 중간에 함수로 점프 할 수있는 언어 제외), 이러한 블록은 함수 내에서 정보가 숨겨져있는 것으로 간주 될 수 있습니다.

이러한 (아마도 약간의) 정의를 취하면, 우리는 예라고 말할 수 있습니다. 함수 내에 기능을 넣는 것은 캡슐화를 구성합니다. 함수 내의 블록의 캡슐화는 첫 번째 그래프입니다.

그러나 경고가 있습니다. 모든 클래스가 공개 된 패키지를 캡슐화 할 패키지를 고려 하시겠습니까? 위의 정의에 따르면, 패키지의 인터페이스 (즉, 모든 공개 클래스)가 실제로 패키지의 동작의 하위 집합을 다른 패키지에 제공한다고 말할 수 있듯이 테스트를 통과합니다. 그러나이 경우 하위 집합은 정보가 숨겨져있는 클래스가 없기 때문에 전체 패키지의 동작입니다. 따라서 위의 정의를 정중하게 만족 시키지만, 우리는 그것이 정의의 정신을 만족시키지 않는다고 생각합니다.

당신이주는 exampe에 대해서도 마찬가지입니다. 우리는 확실히 n = n + 1이 단일 McCabian 블록으로 간주 할 수 있습니다. 그러나 이것을 넣는 기능에는 하나의 블록 만 포함하므로 해당 블록은 기능의 유일한 공개 블록이므로 제안 된 기능 내에 정보 숨겨진 블록이 없습니다. 따라서 그것은 캡슐화의 정의를 만족시킬 수 있지만, 나는 그것이 정신을 만족시키지 않는다고 말할 것입니다.

물론이 모든 것은 그러한 캡슐화 혜택을 입증 할 수 없다면 학문적입니다.

캡슐화에 동기를 부여하는 두 가지 힘이 있습니다 : 시맨틱과 논리.

시맨틱 캡슐화는 단지 캡슐화 된 노드 (일반 용어를 사용하기 위해)의 의미에 기초한 캡슐화를 의미합니다. 그래서 내가 '동물'이라는 두 개의 패키지와 '미네랄'이라고 불리는 두 개의 패키지가 있다고 말한 다음 세 개의 수업 개, 고양이, 염소를주고 어떤 패키지를 캡슐화 해야하는지 묻습니다. 다른 정보는 없으며, 시스템의 의미론은 세 가지 클래스가 '미네랄'이 아닌 '동물'패키지 내에 캡슐화 될 것을 제안 할 것이라고 주장 할 수 있습니다.

그러나 캡슐화에 대한 또 다른 동기는 논리입니다.

시스템의 구성은 시스템의 각 노드와 그 사이에있는 캡슐화 된 영역의 정확하고 철저한 식별입니다. Java 시스템의 특정 구성은 세 번째 그래프에서 시스템의 모든 클래스를 식별하고 각 클래스가 상주하는 패키지를 지정합니다.

시스템을 논리적으로 캡슐화한다는 것은 시스템의 구성에 의존하는 시스템의 일부 수학적 특성을 식별 한 다음 해당 시스템을 수학적으로 최소화하도록 구성하는 것을 의미합니다.

캡슐화 이론은 캡슐화 된 모든 그래프가 최대 전위의 가장자리 (MPE)를 표현할 것을 제안합니다. 예를 들어, 클래스 및 패키지의 Java 시스템에서 MPE는 해당 시스템의 모든 클래스간에 존재할 수있는 최대의 소스 코드 종속성 수입니다. 동일한 패키지 내의 두 클래스는 서로 정보를 숨길 수 없으므로 둘 다 잠재적으로 서로 구분을 형성 할 수 있습니다. 그러나 별도의 패키지의 두 패키지-민간 클래스는 서로 의존성을 형성하지 않을 수 있습니다.

캡슐화 이론은 MPE가 최소화되도록 주어진 수의 클래스에 대해 얼마나 많은 패키지를 가져야하는지 알려줍니다. 이는 부담 원칙의 약한 형태가 엔티티 모음을 변형시키는 최대 잠재적 부담이 전환 된 최대 잠재적 엔터티 수의 함수라고 말하기 때문에 유용 할 수 있습니다. 귀하의 클래스는 특정 업데이트를 수행하는 잠재적 비용이 커집니다. MPE를 최소화하면 최대 잠재적 업데이트 비용이 최소화됩니다.

N 클래스와 패키지 당 P 공개 클래스의 요구 사항이 주어지면, 캡슐화 이론은 패키지의 수 R, MPE를 최소화해야한다는 것을 보여줍니다. R = SQRT (N/P).

이는 시스템의 McCabian 블록의 총 수를 감안할 때 가져야 할 기능의 수에도 적용됩니다. 위에서 언급 한 것처럼 함수는 항상 하나의 공개 블록을 가지고 있으므로 시스템에서 가지고있는 함수 r에 대한 방정식은 다음을 단순화합니다. r = sqrt (n).

물론 캡슐화를 연습 할 때 시스템의 총 블록 수를 고려한 사람은 거의 없지만 클래스/패키지 수준에서 쉽게 수행됩니다. 게다가 MPE를 최소화하는 것 외에도 거의 전적으로 완전히 직관적입니다. 공개 클래스의 수를 최소화하고 패키지를 통해 클래스를 균일하게 배포하려고 시도함으로써 수행됩니다 (또는 적어도 30 개의 클래스, 500 개의 클래스가 포함 된 1 개의 몬스터 Pacakge가있는 대부분의 패키지를 피하십시오. 이 경우 후자의 내부 MPE는 다른 모든 사람들의 MPE를 쉽게 압도 할 수 있습니다).

따라서 캡슐화는 시맨틱과 논리 사이의 균형을 인상하는 것을 포함합니다.

모든 큰 재미.

엄격한 객체 지향 용어에서, 거절하고 싶은 유혹을받을 수 있습니다. "단순한"기능은 캡슐화라고 불리는 것이 충분하지 않습니다 ... 그러나 현실 세계에서 명백한 대답은 "예, 함수는 일부 코드를 캡슐화합니다"입니다.

이 신성 모독을 강하게하는 OO 순수 주의자들에게는 상태와 단일 방법이없는 정적 익명 클래스를 고려하십시오. AddOne () 함수가 캡슐화되지 않으면이 클래스도 아닙니다!

그리고 단지 pedantic이되기 위해, 캡슐화는 그 반대가 아니라 추상화의 한 형태입니다. ;-)

일반적으로 속성에 대한 참조없이 캡슐화를 말하는 것은 일반적으로 의미가 없습니다. 혼자서 방법 - 확실히 방법에 대한 액세스 컨트롤을 넣을 수 있지만, 캡슐화 된 방법에 대한 데이터가없는 데이터 없이는 무의미한 방법이 아닌 방법을 알기가 어렵습니다. 아마도 당신은 그것을 검증하는 주장을 할 수 있지만, 나는 그것이 구불 구불 한 것 같다.

따라서, 당신은 글로벌 기능이 아닌 클래스에 메소드를 넣기 때문에 캡슐화를 사용하지 않을 가능성이 높습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top