프로그래머가 강제로 정의하도록 기본 클래스의 추상 속성


10

임베디드 장치의 상태 패턴으로 코딩하고 있습니다. State라는 기본 / 추상 클래스가 있으며 각 개별 (콘크리트) 상태 클래스는 추상 상태 클래스를 구현합니다.

주 클래스에는 여러 가지 추상 메소드가 있습니다. discrete (concrete) 클래스에서 추상 메서드를 구현하지 않으면 Visual Studio에서 다음과 같은 오류가 발생합니다.

... 오류 1 'myConcreteState'가 상속 된 추상 멤버 'myAbstractState'를 구현하지 않습니다.

이제 StateState라는 각 State에 대해 String 속성을 만들려고합니다. 새로운 구체적 클래스를 만들 때마다 StateName을 정의해야합니다. VS를 사용하지 않으면 오류가 발생하기를 원합니다. 이를 수행하는 간단한 방법이 있습니까?

나는 abstract / base 클래스에서 이것을 시도했다.

public abstract string StateName { get; set; }

그러나 각 주마다 Get 및 Set 메서드를 구현할 필요는 없습니다.

수정 된 질문 : 이상적인 상황에서 각 주 클래스는 StateName을 정의하고 추상 기본 클래스에서 상속해야합니다.

StateName = "MyState1"; //or whatever the state's name is

해당 문이 없으면 Visual Studio는 위에서 설명한대로 오류를 생성합니다. 이것이 가능합니까? 그렇다면 어떻게해야합니까?


2
질문을 이해하지 못합니다.
벤 애런 슨

이것을 수행하는 "올바른"방법은 기본 이름에 매개 변수로 상태 이름이 필요한 보호 생성자를 갖는 것입니다.
Roman Reiner

@RomanReiner 저도 그렇게 생각했습니다.. 매번 상태를 변경 / 호출 할 때마다 중복되는 것처럼 보이므로 이름을 입력해야합니다.
GisMofx 2016

@ BenAaronson 나는 내 질문을 바닥 근처에서 분명히했다.
GisMofx

상태 이름은 유형마다 상수입니까, 인스턴스 당 상수입니까?
Roman Reiner 2018 년

답변:


16

이것을 수행하는 "올바른"방법은 기본 이름에 매개 변수로 상태 이름이 필요한 보호 생성자를 갖는 것입니다.

public abstract class State
{
    private readonly string _name;

    protected State(string name)
    {
        if(String.IsNullOrEmpty(name))
            throw new ArgumentException("Must not be empty", "name");

        _name = name;
    }

    public string Name { get { return _name; } }
}

그러면 구체적인 상태는 기본 클래스 생성자를 적절한 이름으로 암시 적으로 호출하는 공용 생성자를 제공합니다.

public abstract class SomeState : State
{
    public SomeState() : base("The name of this state")
    {
        // ...
    }
}

기본 클래스는 다른 생성자 (보호되거나 공개되지 않음)를 노출하지 않으므로 각 상속 클래스는이 단일 생성자를 거쳐야하므로 이름을 정의해야합니다.

구체적인 상태를 인스턴스화 할 때 생성자가 처리하므로 이름을 제공 할 필요가 없습니다.

var someState = new SomeState(); // No need to define the name here
var name = someState.Name; // returns "The name of this state"

1
감사! 실제로 기본 클래스 생성자는 이제 추가 인수를 취합니다. 두 개의 입력이 있습니다. 이것을 설정하자마자 상태 클래스 생성자에 추가 인수가 필요하다는 오류가 발생합니다 ...:base(arg1, arg2)! 이것은 내가 찾고있는 해결책입니다. 이것은 내 주 코딩을보다 일관성있게 유지하는 데 실제로 도움이됩니다.
GisMofx

3

C # 6에서 (믿습니다 -C # : 새롭고 향상된 C # 6.0 ) getter 전용 속성을 만들 수 있습니다. 기본 클래스를 이렇게 선언 할 수 있습니다.

public abstract class State
{
    public abstract string name { get; }

    // Your other functions....
}

그런 다음 하위 클래스에서 다음 State과 같이 구현할 수 있습니다.

public class SomeState : State
{
    public override string name { get { return "State_1"; } }
}

또는 람다 연산자를 사용하여 더 깔끔합니다.

public class SomeState : State
{
    public override string name => "State_1";
}

둘 다 항상 "State_1"을 반환하고 변경할 수 없습니다.


1
이것은 public override string name { get; } = "State_1";매번 값을 재평가 할 필요가없는 것으로 쓰여질 수 있습니다 .
Dave Cousineau

2

요구 사항은 모순입니다.

StateName이라는 State 에 대해 String 속성을 만들려고합니다 .

vs.

그러나 주 에서 모든 것을 구현할 필요는 없습니다 .

몇 개의 하위 클래스에서만 멤버를 강제로 사용할 수있는 언어 기능이 없습니다. 결국, 수퍼 클래스를 사용하는 요점은 모든 서브 클래스가 수퍼 클래스의 모든 멤버를 가질 것이라는 사실에 의존하는 것입니다. a로 작동 State하지만 이름이없는 클래스를 작성하려면 정의에 따라의 서브 클래스가 아니어야합니다 State.

요구 사항을 변경하거나 단순 상속 이외의 것을 사용해야합니다.

코드가있는 가능한 해결책은 메소드를 State비 추상적으로 만들고 빈 문자열을 반환하는 것일 수 있습니다 .


나는 당신이 문맥에서 두 번째 진술을 취했다고 생각하지만, 분명히 할 것입니다. Get / Set 메서드가 필요하지 않으며 StateName = "MyState1"각 상태에서 간단하게 원합니다 . 상태 클래스에 해당 문이 없으면 Visual Studio에서 오류가 발생하는 것이 이상적입니다.
GisMofx 2016

3
@GisMofx 각 서브 클래스에서 상태 이름을 강제하려면 get abstract를 작성하되 상태는 필요하지 않습니다. 그런 다음 각 서브 클래스는 return "MyState1"구현 으로 제공 해야하며 필요한 경우 값에 대한 가변 스토리지를 추가 할 수 있습니다. 그러나 문제의 요구 사항을 명확히해야합니다. 모든 유형의 상태에는 읽을 수있는 StateName이 필요하며 생성 후에는 모든 유형의 상태가 변경되어야합니까?
피트 Kirkham

@PeteKirkham 각 상태에는 이름이 필요하므로 생성 후 변경해서는 안됩니다. 상태 이름은 정적 / 불변입니다.
GisMofx
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.