문제

기본 클래스와 많은 생성자와 가상 방법

public class Foo
{
   ...
   public Foo() {...}
   public Foo(int i) {...}
   ...
   public virtual void SomethingElse() {...}
   ...
}

그리고 이제 나를 만들려고 하위 클래스는 재정의가 가상 방법:

public class Bar : Foo 
{
   public override void SomethingElse() {...}
}

고 다른 하위는 어떤 더 많은 물건:

public class Bah : Bar
{
   public void DoMoreStuff() {...}
}

나는 진짜로 있을 모두 복사에서 생성자를 Foo 으로 바 및 바?한 다음 변경하는 경우 생성자 서명 Foo,나는 그것을 업데이트 바 및 바?

방법은 없을 상속받을 생성자?방법은 없을 격려하는 코드를 재사용할?

도움이 되었습니까?

해결책

예, 각 파생에 대해 이해하는 생성자를 구현 한 다음 사용해야합니다. base 해당 생성자를 적절한 기본 클래스 또는 this 같은 클래스에서 생성자를 다른 생성자로 지시하는 키워드.

컴파일러가 생성자 상속에 대해 가정 한 경우, 우리는 객체가 어떻게 인스턴스화되었는지를 올바르게 결정할 수 없습니다. 대부분의 경우, 당신은 왜 당신이 왜 그렇게 많은 생성자를 가지고 있는지 고려하고 기본 클래스에서는 하나 또는 2 개로 만 줄이는 것을 고려해야합니다. 파생 된 클래스는 다음과 같은 일정한 값을 사용하여 일부를 가릴 수 있습니다. null 그리고 생성자를 통해 필요한 것을 노출시킵니다.

업데이트

C#4에서는 기본 매개 변수 값을 지정하고 이름이 지정된 매개 변수를 사용하여 단일 생성자가 구성 당 하나의 생성자를 갖지 않고 다중 인수 구성을 지원하도록 할 수 있습니다.

다른 팁

387 생성자 ?? 그것이 당신의 주요 문제입니다. 대신 어때?

public Foo(params int[] list) {...}

예, 387 명의 생성자를 모두 복사해야합니다. 리디렉션하여 재사용을 수행 할 수 있습니다.

  public Bar(int i): base(i) {}
  public Bar(int i, int j) : base(i, j) {}

그러나 그것은 당신이 할 수있는 최선입니다.

너무 나쁘다 우리는 컴파일러에게 명백하다고 말해야한다.

Subclass(): base() {}
Subclass(int x): base(x) {}
Subclass(int x,y): base(x,y) {}

나는 12 개의 서브 클래스로 3 개의 생성자 만 수행하면됩니다. 따라서 큰 문제는 아니지만 오랫동안 글을 쓰지 않아도 된 후 모든 서브 클래스에서 반복하는 것을 좋아하지는 않습니다. 나는 그것에 대한 유효한 이유가 있다고 확신하지만, 나는 이런 종류의 제한이 필요한 문제를 본 적이 없다고 생각합니다.

같은 수준의 상속에서 생성자를 다른 생성자로 리디렉션 할 수도 있다는 것을 잊지 마십시오.

public Bar(int i, int j) : this(i) { ... }
                            ^^^^^

또 다른 간단한 솔루션이 될 수 있을 사용하는 구조 또는 간단한 데이터는 클래스를 매개 변수를 포함합 속성으로;는 방법으로 할 수 있는 모든 기본 값과 동작 설정 시간에 앞서,지나가는"매개변수는 클래스에서는"단일 생성자 매개변수:

public class FooParams
{
    public int Size...
    protected myCustomStruct _ReasonForLife ...
}
public class Foo
{
    private FooParams _myParams;
    public Foo(FooParams myParams)
    {
          _myParams = myParams;
    }
}

이렇게 혼란의 여러 생성자를(가끔)고 강력한 기본값이고,다른 장점에 의해 제공되지 않을 매개 변수 배열입니다.그것은 또한 간편하게 앞으로 수행한 이후 아무것도에서 상속되는 Foo 할 수 있도를,또는 추가,FooParams 으로 필요합니다.당신은 여전히 필요 복사본을 생성자,하지만 당신은 항상(대부분의 시간)만(일반적으로)지금까지(적어도,이제)하나를 필요로 생성자입니다.

public class Bar : Foo
{
    public Bar(FooParams myParams) : base(myParams) {}
}

내가 정말 좋아한 과부 Initailize()와 클래스의 공장 패턴에 접근 방식은 더 나은,그러나 때때로 당신이 있어야의 스마트 생성자입니다.다만 생각했다.

처럼 Foo 클래스는 가상 과부하를 만들 수 없습니다 Initialise() 행동 양식? 그러면 하위 클래스를 사용할 수 있고 여전히 확장 가능합니까?

public class Foo
{
   ...
   public Foo() {...}

   public virtual void Initialise(int i) {...}
   public virtual void Initialise(int i, int i) {...}
   public virtual void Initialise(int i, int i, int i) {...}
   ... 
   public virtual void Initialise(int i, int i, ..., int i) {...}

   ...

   public virtual void SomethingElse() {...}
   ...
}

기본 속성 값이 많고 많은 타격을받지 않는 한 성능 비용이 더 높아서는 안됩니다.

public class BaseClass
{
    public BaseClass(params int[] parameters)
    {

    }   
}

public class ChildClass : BaseClass
{
    public ChildClass(params int[] parameters)
        : base(parameters)
    {

    }
}

개인적으로 나는 이것이 마이크로 소프트 부분의 실수라고 생각합니다. 프로그래머는 기본 클래스에서 생성자, 방법 및 속성의 가시성을 무시하고 생성자가 항상 상속되도록 만들어야합니다.

이런 식으로 우리는 단순히 우리가 원하는 모든 생성자를 추가하는 대신 원하지 않는 생성자를 단순히 (가시성이 낮은) 무시합니다. 델파이는 이런 식으로 그렇게하고 그리워합니다.

예를 들어 System.io.StreamWriter 클래스를 무시하려면 7 개의 생성자를 모두 새 클래스에 추가해야하며 댓글을 달려면 헤더 XML로 각각 댓글을 달아야합니다. 더 나쁘게 만들기 위해 메타 데이터보기 DOSNT는 XML 주석을 적절한 XML 주석으로 넣으므로 라인별로 가서 복사하여 붙여 넣어야합니다. 여기서 Microsoft는 무엇을 생각하고 있었습니까?

실제로 메타 데이터 코드에 붙여 넣을 수있는 작은 유틸리티를 작성했으며 과도한 가시성을 사용하여 XML 주석으로 변환합니다.

모든 생성자를 실제로 복사해야합니까? Foo ~ 안으로 Bar 그리고 Bah? 그런 다음 생성자 서명을 변경하면 Foo, 나는 그것을 업데이트해야합니까? Bar 그리고 Bah?

예, 생성자를 사용하여 인스턴스를 작성하는 경우.

생성자를 상속하는 방법이 없습니까?

아니요.

코드 재사용을 장려 할 방법이 없습니까?

글쎄, 나는 건설자가 좋은 것인지 나쁜 일이 될지 여부와 코드 재사용을 장려 할 것인지 여부에 들어 가지 않을 것입니다. :-)

하지만 2014 년에는 현재 C#을 사용하여 무언가를 얻을 수 있습니다. 처럼 일반을 사용하여 상속 된 생성자 create 대신 방법. 벨트에있는 유용한 도구 일 수 있지만 가볍게 도달하지는 않습니다. 나는 최근에 몇 백 개의 파생 클래스에 사용되는 기본 유형의 생성자로 무언가를 전달해야 할 때 최근에 도달했을 때 (최근까지, 기지에는 인수가 필요하지 않았으므로 기본 생성자는 괜찮 았습니다. 클래스는 생성자를 전혀 선언하지 않았으며 자동으로 제공되는 것들을 얻었습니다).

다음과 같이 보입니다.

// In Foo:
public T create<T>(int i) where: where T : Foo, new() {
    T obj = new T();
    // Do whatever you would do with `i` in `Foo(i)` here, for instance,
    // if you save it as a data member;  `obj.dataMember = i;`
    return obj;
}

그것은 당신이 제네릭을 호출 할 수 있다고 말합니다 create 모든 하위 유형 인 유형 매개 변수를 사용하는 기능 Foo 그것은 제로 연설 생성자가 있습니다.

그런 다음하는 대신 Bar b new Bar(42), 당신은 이것을합니다 :

var b = Foo.create<Bar>(42);
// or
Bar b = Foo.create<Bar>(42);
// or
var b = Bar.create<Bar>(42); // But you still need the <Bar> bit
// or
Bar b = Bar.create<Bar>(42);

거기에서 보여주었습니다 create 방법이 켜져 있습니다 Foo 직접적이지만 물론 공장 수업에 의해 설정중인 정보를 설정할 수 있다면 어떤 종류의 공장 클래스에있을 수 있습니다.

명확성을 위해 : 이름 create 중요하지 않습니다 makeThingy 또는 당신이 좋아하는 것.

전체 예

using System.IO;
using System;

class Program
{
    static void Main()
    {
        Bar b1 = Foo.create<Bar>(42);
        b1.ShowDataMember("b1");

        Bar b2 = Bar.create<Bar>(43); // Just to show `Foo.create` vs. `Bar.create` doesn't matter
        b2.ShowDataMember("b2");
    }

    class Foo
    {
        public int DataMember { get; private set; }

        public static T create<T>(int i) where T: Foo, new()
        {
            T obj = new T();
            obj.DataMember = i;
            return obj;
        }
    }

    class Bar : Foo
    {
        public void ShowDataMember(string prefix)
        {
            Console.WriteLine(prefix + ".DataMember = " + this.DataMember);
        }
    }
}

문제는 Bar와 BAH가 387 개의 생성자를 복사해야한다는 것이 아니라 문제는 FOO에 387 개의 생성자가 있다는 것입니다. Foo는 너무 많은 일을 분명히합니다 - Refactor Quick! 또한 생성자에 값을 설정해야 할 이유가 없다면 (매개 변수가없는 생성자를 제공하는 경우, 아마도 그렇지 않을 것입니다) 속성 Geting/Setting을 사용하는 것이 좋습니다.

아니요, 387 개의 생성자를 모두 막대와 BAH에 복사 할 필요는 없습니다. Bar와 Bah는 FOO에서 얼마나 많은 정의를 정의하는지와 무관하게 원하는만큼의 생성자를 가질 수 있습니다. 예를 들어, FOO의 212 번째 생성자로 FOO를 구성하는 하나의 막대 생성자 만 있도록 선택할 수 있습니다.

그렇습니다. Bar 또는 BAH에 의존하는 FOO에서 변경 한 모든 생성자는 BAR과 BAH를 수정해야합니다.

아니요, .NET에는 생성자를 물려받을 방법이 없습니다. 그러나 서브 클래스 생성자 내부의 기본 클래스 생성자를 호출하거나 정의하는 가상 메소드를 호출하여 코드 재사용을 달성 할 수 있습니다 (initialize ()).

버전을 조정할 수 있습니다. C ++ 가상 생성자 관용구. 내가 아는 한, C#은 공분산 반환 유형을 지원하지 않습니다. 나는 그것이 많은 사람들의 소원 목록에 있다고 생각합니다.

너무 많은 생성자는 디자인이 깨진 징후입니다. 생성자가 거의없고 속성을 설정하는 능력을 갖춘 클래스가 더 좋습니다. 속성을 실제로 제어 해야하는 경우 동일한 네임 스페이스의 공장을 고려하고 속성 세터를 내부로 만드십시오. 공장에서 클래스를 인스턴스화하고 속성을 설정하는 방법을 결정하게하십시오. 공장에는 객체를 올바르게 구성하는 데 필요한만큼 많은 매개 변수를 취하는 메소드가있을 수 있습니다.

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