Home > OS >  How to make an abstract getter in C# so you don't have to declare in every child?
How to make an abstract getter in C# so you don't have to declare in every child?

Time:05-08

I have an abstract class that has a implements a abstract method, that works as a placeholder for the getters of a certain value in its childs:

public abstract class MyAbstractClass {
    public abstract int GetMyValue();
}

public class MyChildClass0 : MyAbstractClass {
    int myValue = 1;

    public override int GetMyValue {
        return myValue;
    }
}

public class MyChildClass1 : MyAbstractClass {
    int myValue = 7;

    public override int GetMyValue {
        return myValue;
    }

As you can see, the getter behaves the same way in every child. My question is if there is any way to make that getter a non-abstract method, so I just have to implement it once in the abstract class. And everytime I want to access myValue in any child class, I just call the GetMyValue method that it inherits from MyAbstractClass.

I don't know how to do it because I don't know how to make the getter access that field, since it is not declared in the abstract class, but in the childs.

CodePudding user response:

Properties and a default constructor are a great thing here.

This forces all derived classes to provide the value to MyAbstractClass.

public abstract class MyAbstractClass {
    protected MyAbstractClass(int myValue) 
    {
       MyValue = myValue;
    }
    public int MyValue { get; }
}

CodePudding user response:

In your specific case you want an int tightly coupled to the implementation class, but is exposed readonly publicly, but also presumably you want Compilation Time errors, not Runtime errors, if someone forgot to set MyValue on the class, and the value is specified at the Class level, not the Constructor level (the thing that creates an instance of your class cannot set/modify the classes MyValue, its inherent to the class)

The following will work:

public abstract class MyAbstractClass {
    public abstract int MyValue { get; }
}

public class MyChildClass0 : MyAbstractClass {
    // C#6 I believe added this handy shorthand for Getter Properties
    public override int MyValue => 1;
}

public class MyChildClass1 : MyAbstractClass {
    // This is the same as above
    public override int MyValue {
        get => 7;
    }
}

The compiler will pester you and demand that MyValue is implemented on your implementation concrete class before it will compile, which is ideal, as this enforces it to be set.

CodePudding user response:

Since GetMyValue is going to always return myValue why you can't just move myValue into the abstract class?

Something like this:

public abstract class MyAbstractClass {
    int myValue;

    public int GetMyValue() {
        return myValue;
    }

    // If you want to change myValue you could also create a setter
    public int SetMyValue(int myValue) {
        this.myValue = myValue;
    }
}

public class MyChildClass0 : MyAbstractClass {
    public MyChildClass() {
        // In constructor you can call a setter to update your value
        SetMyValue(1);
        // Or you could mark myValue as a protected field so 
        // that MyAbstractClass children had access to it. 
        // Then you could just directly assign a value to it
    }
}

public class MyChildClass1 : MyAbstractClass {
    public MyChildClass1() {
        SetMyValue(7);
    }
}
  • Related