2008-12-03 3 views
17

'Application'클래스가 있다고 가정합니다. 초기화되기 위해서는 생성자에서 특정 설정이 필요합니다. 또한 설정의 수가 너무 많아서 자신의 클래스에 배치하는 것이 중요하다고 가정 해 보겠습니다."Public"중첩 클래스가 아닌지

이 시나리오의 두 가지 구현을 비교해보십시오.

구현 1 :

class Application 
{ 
    Application(ApplicationSettings settings) 
    { 
     //Do initialisation here 
    } 
} 

class ApplicationSettings 
{ 
    //Settings related methods and properties here 
} 

구현 2 : 나에게

class Application 
{ 
    Application(Application.Settings settings) 
    { 
     //Do initialisation here 
    } 

    class Settings 
    { 
     //Settings related methods and properties here 
    } 
} 

는, 두 번째 방법은 매우 바람직하다. 그것은 두 클래스 사이의 관계를 강력하게 강조하므로 더 읽기 쉽습니다. Application 클래스를 어디서나 인스턴스화하는 코드를 작성할 때 두 번째 접근법이 더 예쁘게 보일 것입니다.

이제 설정 클래스 자체가 유사하게 "관련"클래스를 가지고 있다고 가정 해보십시오. 그리고 그 클래스도 마찬가지로 그렇게했습니다. 그러한 레벨을 세 단계 만 가면 클래스 네이밍은 '중첩되지 않은'경우에 발생합니다. 그러나 둥지를 틀면 물건은 여전히 ​​우아합니다. 중첩 된 클래스들은 외부 세계에 표시하지 않은 경우에만 정당화되어 있는지에 StackOverflow에 말

위에도 불구하고, 내가 읽은 사람; 즉, 클래스를 포함하는 클래스의 내부 구현에만 사용되는 경우입니다. 일반적으로 언급 된 이의 제기는 클래스의 소스 파일을 포함하는 크기를 늘리는 것이지만 부분 클래스는 그 문제에 대한 완벽한 해결책입니다.

제 질문은 중첩 된 클래스의 "공개적으로 노출 된"사용에주의해야하는 이유는 무엇입니까? 그러한 사용에 반대하는 다른 주장이 있습니까?

답변

22

나는 괜찮다고 생각한다. 이것은 기본적으로 빌더 패턴이며, 중첩 클래스를 사용하면 꽤 잘 작동합니다. 또한 빌더는 외부 클래스의 전용 멤버에 액세스 할 수 있으므로 매우 유용 할 수 있습니다. 예를 들어, 빌더의 인스턴스를 취 외부 클래스에 개인 생성자를 호출 빌더의 작성 방법을 가질 수 있도록

public class Outer 
{ 
    private Outer(Builder builder) 
    { 
     // Copy stuff 
    } 

    public class Builder 
    { 
     public Outer Build() 
     { 
      return new Outer(this); 
     } 
    } 
} 

그의 인스턴스를 구축 방법 바깥 쪽 클래스는 빌더를 통해 있습니다.

프로토콜 버퍼의 C# 포트에서 이와 비슷한 패턴을 사용합니다.

+0

최근 빌더 코드를 작성하고이 게시물을 기억했습니다. 그것은 매우 유용한 접근 방법으로 밝혀졌습니다. 감사합니다. –

+0

* "빌더가 외부 클래스의 전용 멤버에 액세스 할 수도 있습니다."* 명시 적 참조 만 사용하면 정확합니다 (Java의 내부 클래스처럼 암시 적이 아님). – samosaris

+0

@SamusArin : 예, 포함하는 클래스의 인스턴스에 대한 암시 적 참조는 없습니다. 그러나 정적 멤버에 액세스 할 수도 있습니다. 기본적으로 나는 접근성에 대해서만 이야기했다. –

0

어떤 주제에서 Microsoft has to say을 확인하고 싶을 것입니다. 기본적으로 그것은 스타일에 대한 질문입니다.

+0

.NET은 Java가 수행하는 "파일 당 하나의 공용 클래스"규칙을 적용하지 않습니다. 그들은 프로그램 구조와는 다른 패러다임을 가지고있는 것처럼 보입니다. 이 규칙을 혼자서 WRT하면 .NET에 유연성이 더해진다. 훌륭한 기사 btw. – samosaris

0

주로 중첩 된 클래스 및/또는 컨테이너 클래스에 대한 액세스를 미세 조정하기 위해 중첩 된 클래스를 사용합니다. 기억해야 할

한 가지 중첩 된 클래스 정의는 기본적으로 클래스 멤버이며, 컨테이너의 private 변수 모두에 액세스 할 수 있다는 것입니다.

특정 클래스의 사용을 제어하는데도 사용할 수 있습니다.

예 : 그는 외부를 구현하는 경우

public abstract class Outer 
{ 
    protected class Inner 
    { 
    } 
} 

지금,이 경우, (클래스의) 사용자는, 내부 클래스에 액세스 할 수 있습니다.

+1

Iff는 오타가 아닐 수도 있지만 문장에 "유일한"단어가 있으므로 * 다소 중복됩니다. – phoog

5

네임 스페이스를 사용하면 관련된 것들을 연결할 수 있습니다. 예를 들어

:

namespace Diner 
{ 
    public class Sandwich 
    { 
     public Sandwich(Filling filling) { } 
    } 

    public class Filling { } 
} 
그들이 네임 스페이스 것처럼 클래스를 사용하여 이상이의 장점은 당신이 선택적 일 생략하기 위해 호출 측에 using를 사용할 수 있다는 것입니다

:

using Diner; 

... 

var sandwich = new Sandwich(new Filling()); 

을 당신이 만약 Sandwich 클래스를 Filling의 네임 스페이스 인 것처럼 사용하십시오. 을 참조하려면 전체 이름 Sandwich.Filling을 사용해야합니다.

밤에 어떻게 그걸 알면 자려고합니까?

+2

나는 네임 스페이스에 대한 선호에 동의하지만 때로는 잘 작동하지 않는 경우도있다. 예를 들어, 문제의 예제에서 의미 론적으로 'Application'은 'Settings'을 포함하지만 둘 다 공통 네임 스페이스에 넣으면 그 의미를 전달하지 않습니다. –

+0

**'Filling = Diner.Filling; 사용 ** '은'클래스를 네임 스페이스로 사용하는 경우 '**'채우기 '**에 대한 "참조"를 해결해야합니다. – samosaris

0

IEnumerable 속성으로 viewmodel을 사용할 때 공용 중첩 클래스를 올바르게 사용하는 또 다른 유용한 예는 MVC 패턴입니다. 예를 들면 : 나는 그것이 단지를 포함하는 특정 뷰 모델에 맞게 사용자 정의되어 있기 때문에 Product 클래스는 외부 다시 사용할 수 싶지 않기 때문에

public class OrderViewModel 
{ 
public int OrderId{ get; set; } 
public IEnumerable<Product> Products{ get; set; } 

public class Product { 
public string ProductName{ get; set; } 
public decimal ProductPrice{ get; set; } 
} 

} 

나는 그것을 사용합니다. 그러나 Products 속성이 공개되어있어 비공개로 설정할 수는 없습니다.

관련 문제