2017-02-24 1 views
1

추가 속성을 추가하고자하는 외부 라이브러리의 클래스 개체가 있습니다.추가 속성으로 클래스 확장하기

public class ExternalClass 
{ 
    public string EXproperty1 {get;set;} 
    public string EXproperty2 {get;set;} 
    public string EXproperty3 {get;set;} 

    public ExternalClass(){} 
} 

그리고 내가 추가, 나는 새로운 클래스를 생성하여이 클래스를 확장 할 수 있습니다

List<ExternalClass> listOfExternalClass=new List<ExternalClass>(); 
listOfExternalClass=GetListOfExternalClass(); 

로 채워됩니다 이러한 개체의 목록을 가지고 :

의 외부 클래스가 있다고 가정 해 봅시다 추가 속성을 만들고 외부 클래스를 속성으로 만듭니다. 나는 새로운 클래스의 새 목록을 만들고 원래 목록 새로운 객체를 생성하고에 추가 반복해야 새로운 클래스 목록에 외부 클래스의 원래 목록으로 변환하는 그러나

public class NewClass 
{ 
    public ExternalClass ExternalClass {get;set;} 
    public string NewProperty1 {get;set;} 
    public string NewProperty2 {get;set;} 

    public NewClass(){} 
    public NewClass(ExternalClass externalClass){ 
     this.ExternalClass=externalClass; 
    } 
} 

목록,

List<NewClass> listOfNewClass=new List<NewClass>(); 
foreach(var externalClass in listOfExternalClass) 
{ 
    listOfNewClass.Add(new NewClass(externalClass)); 
} 

처럼 그때 내가 상속이 작업을 수행하거나 더 효율적인 방법이있을 수

listOfNewClass.FirstOrDefault().ExternalClass.EXproperty1; 

같은 외부 속성에 액세스 할 수있을 것입니다?

이상적으로 내가 좋아하는 속성을 호출하여 끝낼 싶습니다 :

listOfNewClass.FirstOrDefault().EXproperty1; 
+4

이유 inheretance하지 :

다음은을 바꾸기로 선동 수있는 두 가지 예? 벌써 해봤 니? –

+0

이 질문은 항상 여러 개의 대답이 모두 같은 결과를 낳습니다. – MickyD

+0

[Eric Lippert의 모나드 블로그 시리즈] (https://ericlippert.com/2013/02/21/monads-part-one) . – OldFart

답변

3

그 달성하기 쉽습니다 :

public class NewClass: ExternalClass 
{ 
    public string NewProperty1 {get;set;} 
    public string NewProperty2 {get;set;} 

    public NewClass(){} 
    public NewClass(ExternalClass externalClass){ 
     // you would have to copy all the properties 
     this.EXproperty1 = externalClass.EXproperty1; 
    } 
} 
+0

이것은 내가 시작한 것이지만지도 할 속성이 너무 많습니다. 또한 외부 클래스의 속성 중 하나라도 변경되거나 추가/제거되는 경우 문제가 될 수 있습니다. – DeclanMcD

+0

아하, 아마도 완전히 동적 인 무언가,하지만 너무 복잡 할 수도 있습니다. http://stackoverflow.com/questions/3810488/adding-a-property-to-an-existing-class –

+0

또는 모든 속성을 자동으로 복사하려면 다음을 참조하십시오. http : //stackoverflow.com/questions/930433/apply-properties-values-from-one-object-to-another-of-the-same-type-automaticall –

1

상속은 당신이 무엇을 찾고 예 : 실제로 외부 클래스를 확장 할 수있는 경우

public class ExternalClass 
{ 
    public string EXproperty1 { get; set; } 
    public string EXproperty2 { get; set; } 
    public string EXproperty3 { get; set; } 

    public ExternalClass() { } 
} 

public class NewClass:ExternalClass 
{    
    public string NewProperty1 { get; set; } 
    public string NewProperty2 { get; set; } 
    public NewClass() { }   
} 
3

이것은 확실히 상속을 통해 수행 할 수 있습니다. 다음을 고려하세요.

//Inherit from our external class 
public class NewClass: ExternalClass 
{ 
    //Note we do not have a copy of an ExternalClass object here. 
    //This class itself will now have all of its instance members. 
    public string NewProperty1 {get;set;} 
    public string NewProperty2 {get;set;} 

    //Base will call the constructor for the inherited class. 
    //If it has parameters include those parameters in NewClass() and add them to base(). 
    //This is important so we don't have to write all the properties ourself. 
    //In some cases it's even impossible to write to those properties making this approach mandatory. 
    public NewClass(): base() 
    { 

    } 
} 

몇 가지 알아야 할 사항

  • 귀하의 코드가 래퍼라고합니다. 다른 클래스 또는 클래스 그룹을 "래핑"하기 때문입니다.
  • 봉인 된 클래스에서 상속받을 수 없습니다.
  • C# 클래스는 기본적으로 봉인되어 있지 않습니다. 사용자가 봉인 된 경우 개발자가 의도적으로 클래스에서 상속하지 못하게합니다. 이것은 보통 좋은 이유입니다.
1

대신 사본 (또는 필요) 임용하고자하는 경우 당신이 할 수 있습니다

public class NewClass 
{ 
    public ExternalClass ExternalClass {get;set;} 
    public string NewProperty1 {get;set;} 
    public string NewProperty2 {get;set;} 

    public string EXproperty1 {get { return this.ExternalClass.EXproperty1; };set{ this.ExternalClass.EXproperty1 = value; }; } 
    public string EXproperty2 {get { return this.ExternalClass.EXproperty2; };set{ this.ExternalClass.EXproperty2 = value; }; } 
    public string EXproperty3 {get { return this.ExternalClass.EXproperty3; };set{ this.ExternalClass.EXproperty3 = value; }; } 

    public NewClass(){} 
    public NewClass(ExternalClass externalClass){ 
     this.ExternalClass=externalClass; 
    } 
} 
+0

+1 이것은 내가 수업을 봉인 할 때 할 수있는 것을 채워서 타이핑하고 칭찬하는 것입니다. 단점은 다형성이 없다는 것입니다. –

0

을 대신 특정 유형의 인터페이스에 대한 작업에 대한 작업. 내가 잘 정의 된 인터페이스 (IDocument)에 외부 데이터를 '변환'하는 facade patternadapter pattern의 혼합을 표시하고 아래

, 효율적으로 작업중인 일을 추상화.

예 1 : 인터페이스에 대한 쿼리 여기

당신이에 반대거야 유형은 다음과 같습니다

public class RichDocument : IDocument, IMetadata { 
    public string Name { get; set; } 
    public string[] Tags { get; set; } 
} 
:

public interface IDocument { 
    string Name { get; set; } 
} 

public interface IMetadata { 
    string[] Tags { get; set; } 
} 

이 자신의 표현입니다, 당신은 어떤 필요로한다

외부 데이터에 대한 래퍼입니다.

(210)

(외관 및/또는 어댑터의 자식 믹스 개념)

public class ExternalClass { 
    public string Whatever { get; set; } 
} 

public class ExternalDocument : IDocument /* only a basic object */ { 
    private readonly ExternalClass _class; 

    public ExternalDocument(ExternalClass @class) { 
     _class = @class; 
    } 

    public string Name { 
     get { return _class.Whatever; } 
     set { _class.Whatever = value; } 
    } 
} 

그리고 모든 것을 사용하는 방법에 대한 데모 :

internal class Demo1 { 
    public Demo1() { 
     var documents = new List<IDocument> { 
      new ExternalDocument(new ExternalClass()), 
      new RichDocument() 
     }; 

     foreach (var document in documents){ 
      var name = document.Name; 
      Console.WriteLine(name); 

      // see if it implements some interface and do something with it 
      var metadata = document as IMetadata; 
      if (metadata != null) { 
       Console.WriteLine(metadata.Tags); 
      } 
     } 
    } 
} 

예 2 : 구성 요소

에 대한 쿼리를

이것은 조금 더 관념을 추진하여 모든 것을 통일 된 방식으로 처리합니다. .NET 프레임 워크, 게임 개발 등에서 찾을 수 있습니다.

당신이에 반대합니다

정의 :

public interface IContainer { 
    IList<IComponent> Components { get; } 
} 

public interface IComponent { 
    // it can be/do anything 
} 

일부 구성 요소는 쿼리 수 있습니다에 대한 :

public interface IDocument : IComponent { 
    string Name { get; set; } 
} 

public interface IMetadata : IComponent { 
    string[] Tags { get; set; } 
} 

귀하의 '내부'유형 : 외부에 대한

public class Container : IContainer { 
    public Container() { 
     Components = new List<IComponent>(); 
    } 

    public IList<IComponent> Components { get; } 
} 

귀하의 '래퍼' 데이터 :

public class ExternalClass { 
    public string Whatever { get; set; } 
} 

public class ExternalContainer : IContainer { 
    private readonly List<IComponent> _components; 

    public ExternalContainer(ExternalClass @class) { 
     _components = new List<IComponent> {new ExternalDocument(@class)}; 
    } 

    public IList<IComponent> Components { 
     get { return _components; } 
    } 
} 

public class ExternalDocument : IDocument { 
    private readonly ExternalClass _class; 

    public ExternalDocument(ExternalClass @class) { 
     _class = @class; 
    } 

    public string Name { 
     get { return _class.Whatever; } 
     set { _class.Whatever = value; } 
    } 
} 

그리고 사용 예 :

public class Demo2 { 
    public Demo2() { 
     var containers = new List<IContainer> { 
      new ExternalContainer(new ExternalClass()), 
      new Container() 
     }; 

     foreach (var container in containers) { 
      // query container for some components 

      var components = container.Components; 

      var document = components.OfType<IDocument>().FirstOrDefault(); 
      if (document != null) { 
       Console.WriteLine(document.Name); 
      } 

      var metadata = components.OfType<IMetadata>().FirstOrDefault(); 
      if (metadata != null) { 
       Console.WriteLine(metadata.Tags); 
      } 
     } 
    } 
} 

노트

상속의 문제는 매우 엄격한 접근하고 있다는 것이다 일반적으로 당신은 그 일을 시작하고 어떤 점에서 당신은 벽에 부딪하고 싶어하면 되돌리려면 빠져 나오기가 어렵습니다.

추상화에 반대하여 작업하면 더욱 유연 해지고 모든 것들이 분리됩니다.

Composition over inheritance

Using Components

+0

당신이 옳다면, 컴포지션 (또는 위임)이 많은 경우 이동 방법이지만, 유형 계층 구조는 간단한 문제에 엄청난 복잡성을 초래합니다. 실제로 KISS (https://en.wikipedia.org/wiki/KISS_principle)는 실제로 여러 유형의 객체로 작업해야합니다. –

+0

당신은 100 % 권리입니다. 사람들에게 말해주는 것이지만 대부분의 시간은 나 자신을 잊어 버린다. – Aybe