문제

여기서 내 문제는 파생 클래스에 객체를 전달하고 싶지만 기본 클래스가 즉시 파생 클래스를 호출하기 때문에 기본 클래스 생성자 앞에서 수행해야한다는 것입니다. Start() 객체를 사용하는 방법.

다음은 기본 클래스의 발췌문입니다 (이름이 바뀌 었습니다. 바코드 스캐너 편의상).

public abstract class MyBase
{    
    public MyBase()
    {
        if (Initialize())
            this.Start();
    }

    public abstract bool Initialize();
    public abstract void Start();
}

여기 내가 만든 파생 수업이 있습니다.

class MyDerived : MyBase
{
    private string sampleObject;

    public MyDerived (string initObject)
    {
        sampleObject = initObject;
    }

    public override bool Initialize() 
    { 
        return GetDevice();
    }
    public override void Start() 
    { 
        Console.WriteLine("Processing " + sampleObject.ToString()); 
    }
}

기본 생성자 전에 C#을 파생 생성자를 실행할 수 있다고 의심 스럽다. 그래서 저는 객체를 사용하기 전에 파생 클래스에 객체를 전달할 수있는 해결책을 찾고 있습니다.

초기화/시작 IF 블록을 MyDerived 건설자. 그러나 기본 클래스에서 도출되는 다른 클래스가 있습니다. 그래서 나는 모든 파생 클래스 에서이 초기화/시작 코드 블록을 반복해야했습니다. 기본 클래스를 수정하는 대안을보고 싶습니다.

도움이 되었습니까?

해결책

당신이하려는 것은 C#에서 불가능합니다. 기본 클래스의 생성자는 파생 된 클래스의 생성자 전에 실행되어야합니다. 그렇지 않으면 손상된 객체 상태에 대한 가능성이 있습니다. 하위 물체는 기본이 완전히 구성되고 이용 가능하다고 가정 할 수 있어야합니다.

다른 팁

IMHO 당신의 디자인은 잘못되었습니다. 생성자 내에서 프로세스를 시작해서는 안됩니다. 소비 코드는 필요한 경우 시작 () 메소드를 명시 적으로 호출해야합니다.

초기화 (및 잠재적으로 start () - 일반적으로 이것이 구조 후에 호출되는 공개 메소드가 될 수 있도록 디자인을 재 작업 할 것입니다.

Barcodescanner를 만드는 경우 처음으로 스캔 할 때이를 수행 할 수 있습니다. 파생 클래스의 데이터를 사용하여 회원을 게으른 이니티얼로 만듭니다.

이것은 사용자의 사용법이 실제로 변경되지 않으면 서 문제를 해결합니다.

오래된 스레드에 추가해서 죄송하지만 누군가가 다른 답변에 관심이있을 수 있습니다. 나는 상속이 관련된 클래스 생성자에 필드를 할당하는 것보다 더 많은 일을하는 논리를 처리하는 (IMO) 깔끔한 방법을 발견했습니다. 여기. 이 특정 계층 구조에 대해서는 인터페이스와 확장 방법이있는 일반 솔루션을 사용하지 않으려면 다음과 같은 한 클래스 트리에서 동일한 개념을 사용할 수 있습니다.

public abstract class MyBase
{    
    protected MyBase()
    {
        if (Initialize(this)) // just to illustrate; this will never pass here as this class is abstract
            this.Start();
    }

    protected bool IsInitialized { get; private set; } = false;

    protected static bool Initialize<T>(T instance) where T: MyBase
    {
        if (instance?.GetType() == typeof(T)) // check if this is called from the constructor of instance run time type
            return instance.IsInitialized || ( instance.IsInitialized = instance.Initialize() );
        return false;
    }

    protected abstract bool Initialize();
    public abstract void Start();
}

그리고 파생 :

class MyDerived : MyBase
{
    private string sampleObject;
    protected bool started = false;

    public MyDerived (string initObject)
    {
        sampleObject = initObject;
        if (Initialize(this)) // if this is the most derived constructor, this will run Initialize() and return whether it was successful
            this.Start();
    }

    protected override bool Initialize() 
    { 
       return GetDevice();
    }

    public override void Start() 
    { 
        // if Start() would be protected, we don't need the IsInitialized property and we can move this check to the constructor on the returned value of the Initialize<T>() call.
        if (!IsInitialized) throw new InvalidOperationException("Initialization failed.");
        // if you want to have this method exposed public, we need to check if this instance is successfully initialized from the constructor and not in started state already.
        if (started) return;

        Console.WriteLine("Processing " + sampleObject.ToString()); 
        started = true;
        if (!Run(sampleObject)) started = false;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top