숨기기와 관련하여 C #에서 "새로운"수정 자의 실제적인 용도는 무엇입니까?


21

동료와 나는 new숨은 개념에 적용되는 C # 에서 키워드 의 동작을보고있었습니다 . 에서 문서 :

새 수정자를 사용하여 기본 클래스에서 상속 된 멤버를 명시 적으로 숨길 수 있습니다. 상속 된 멤버를 숨기려면 동일한 이름을 사용하여 파생 클래스에서 멤버를 선언하고 새 수정 자로이를 수정하십시오.

우리는 문서를 읽었으며 기본적으로 무엇을하고 어떻게하는지 이해합니다. 우리가 실제로 처리 할 수없는 것은 처음부터 처리 해야하는 이유입니다. 수정자는 2003 년부터 존재 해 왔으며 우리는 .Net과 그보다 오랫동안 협력 해 왔으며 결코 나오지 않았습니다.

실제 행동에서이 행동이 언제 필요할까요 (예 : 비즈니스 사례에 적용)? 이 기능이 유용하지 못하거나 우리가하는 일 (특히 웹 양식 및 MVC 응용 프로그램 및 일부 작은 요소 WinForms 및 WPF)에서 흔히 볼 수없는 기능입니까? 이 키워드를 사용해보고 사용하면 잘못 사용했을 때 약간 위험한 행동을 할 수 있습니다.

약간 개방 된 것처럼 들리지만이 특정 도구가 유용한 비즈니스 응용 프로그램에 적용 할 수있는 특정 사용 사례를 찾고 있습니다.


9
아마 당신도 그것을 읽었 지 만 왜 메소드 숨기기가 C #에 추가되었는지 Eric Lippert (C # 컴파일러 개발자)의 흥미로운 기사가 ​​있습니다 : blogs.msdn.com/b/ericlippert/archive/2008/05/21/… . 그것은 귀하의 질문의 일부에 대한 답변이지만, 귀하를 위해 비즈니스 사례가 준비되어 있지 않으므로 의견을 달았습니다.
Jalayn 2016 년

3
@Jalayn : 비즈니스 사례는 Eric이이 글에서 토론합니다 : blogs.msdn.com/b/ericlippert/archive/2004/01/07/…
Brian

답변:


22

이를 사용하여 반환 유형 공분산을 모방 할 수 있습니다. 에릭 Lippert의의 설명 . Eric은 다음 예제 코드를 제공합니다.

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    public new Fish Contents() { ... }
    protected override Animal GetContents() { return this.Contents(); }
}

이것은 해결 방법입니다. public override Fish Contents() { ... }안전 함에도 불구하고 합법적이지 않습니다.

일반적으로, 당신은해야 되지 는 클래스의 소비자들에게 혼란으로 (위의 구체적인 예는이 문제에서 고통을하지 않습니다), 법 숨기기를 사용합니다. 기존 메소드를 대체하지 않으려면 새 메소드의 이름을 다른 것으로 지정하십시오.

메서드 숨기기가 필요한 실제 상황은 기본 클래스 공급자가 파생 클래스에 이미 추가 한 일반 메서드를 추가 한 경우입니다. 이러한 프로그램은 새로운 키워드없이 컴파일 (및 경고)하지만 new"이 방법의 내 버전이 기본 클래스의 버전을 대체하고 있다는 것을 알고 있습니다.이 방법은 끔찍하고 혼동 스럽지만 문제가 있습니다." 파생 클래스가 메소드의 이름을 바꾸도록 강제하는 것보다 여전히 낫습니다.

파생 된 메서드를 재정의 된 것으로 취급하면 문제가 발생할 수 있습니다. 컴파일러 구현에 대한 우려를 무시하면서 새 메소드는 기본 메소드와 의미가 다르지만 다형성으로 인해 동일한 이름의 메소드를 호출하도록 요청하면 새 메소드가 호출됩니다.

이 상황은 Eric Lippert 의이 게시물 에서 자세히 설명 합니다.


1
+1 new마커 인은 "이 끔찍한 혼란입니다."
Avner Shahar-Kashtan

Eric의 예제는 비슷한 상황에 있기 때문에 매우 유용하다고 생각합니다 ... TBase를 반환하는 사소한 메소드를 구현하는 기본 클래스와 TDerived를 반환 해야하는 파생 클래스가 있습니다. 이 경우 필요한 악인처럼 느껴집니다.
Kyle Baran

4

언어 디자이너들이 생각하지 못한 것을하기 위해 필요할 수 있다고 생각합니다. C #은 여러 가지면에서 초기 버전의 Java에 대한 반응이었습니다. 그리고 자바가 한 가지 일은 개발자를 발로 쏘아내는 개발자의 가능성을 없애기 위해 개발자를 매우 명시 적으로 피하는 것이 었습니다. C #은 약간 다른 접근 방식을 취했으며 개발자에게 약간의 기회를 부여하여 개발자가 직접 발을 쏠 수있는 기회를 제공했습니다. 한 가지 예가 unsafe키워드입니다. 이 new키워드는 다른 키워드입니다.

이제는 아마도 유용 unsafe하지는 않지만 일단 언어 사양에 들어가면 언어 사양을 벗어나기가 어렵습니다.


5
Java는 모든 메소드를 가상으로 처리하므로 Java에는 새로운 기능이 없습니다. 에릭 리퍼 트 ​​(Eric Lippert)에 따르면, 새로운 지원 동기는 취성 기본 계급 문제를 해결하는 것이라고합니다. 새로운 수준의 존재는 저수준 라이브러리 사용뿐만 아니라 실제 비즈니스 사용에도 필요합니다. Java가 새롭지 않고 (가상 메소드를 가지지 않음) 기본 클래스가 파생 클래스에서 이미 사용중인 새 메소드를 도입하면 기본 클래스의 개발자가 허용되어야한다는 사실에도 불구하고 기존 코드가 중단 될 수 있음을 의미합니다. 그것을 소비하는 코드를 잊어 버리는 것.
Brian

3

독자에게 우연히 "이 방법의 기본 클래스 구현을 의도적으로 숨겼습니다"라고 말합니다.


5
이것은 나에게 질문을 구걸로 파업. OP는 자신이하는 일을 알고 있지만 그 이유를 알고 싶어합니다.
Brian

0

다른 이름을 통해 이전 멤버를 사용 가능하게 할 수 있습니다.

class VehicleClass
{
  public int AnyProperty
  {
    get; set;
  }

  public int AnyFunction() { return 0; }
} // VehicleClass

class IntermediateClass : VehicleClass
{
  public int PreviousAnyProperty
  {
    get { return AnyProperty; }
    set { AnyProperty = value  }
  }

  public int PreviousAnyFunction() { return AnyFunction(); }
} // IntermediateClass 

class CarClass : IntermediateClass
{
  public new int AnyProperty
  {
    get ; set ;
  }

  public new int AnyFunction() { return 5; }
} // class CarClass

class ExampleClass
{

  public static void Main()
  {
    using (CarClass MyCar = new CarClass())
    {
      int AnyInt1 = MyCar.PreviousAnyProperty;
      MyCar.PreviousAnyProperty = 7;

      int AnyInt2 = MyCar.PreviousAnyFunction();

      int AnyInt3 = MyCar.AnyProperty;
      MyCar.AnyProperty = 45;

      int AnyInt4 = MyCar.AnyFunction();
    }
  } // static void Main()

} // class CarClass

건배.


작동 방식에 익숙하지만 제 질문은 이전 회원을 다른 이름으로 이용할 수있게 하시겠습니까? 이것은 모든 종류의 계약을 어 기고, 특정 일반 부분을 쓸모 없게 만듭니다.
Joel Etherton

@Joel Etherton : 알다시피 개발자가 다른 사람들에게 프로그래밍 코드를 "선택"해야하는 경우가 있습니다. 그리고 우리는 클래스를 수정하거나 확장 할 수있는 권한이 없습니다. 이전 멤버와 새 멤버를 모두 사용해야 할 수도 있습니다.
umlcat 2016 년

0

레거시 코드에 대한 테스트 스위트를 만들 때 매우 유용하다는 것을 알았습니다. 다른 메소드에서 사용하는 메소드 내부에서 데이터베이스를 조회하는 것과 같이 외부 종속성을 숨길 수 있습니다. 다른 메소드를 테스트 할 수 있도록 테스트 클래스의 해당 메소드에 virtual 키워드를 추가하지 않고도 외부 자원에 의존하는 원래 논리를 숨길 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.