MrFox
MrFox

Reputation: 5116

How to make abstract static properties

I know this can be done for methods by using an interface. But interfaces cannot have fields or static properties (which would not help because it would specify one value for all classes that implement the interface). I could also have default values for the properties at the abstract class. But ideally I'd like to force every inheriting class to implement values for these properties. Values which can then still be used in abstract methods on the abstract class level.

The benefits of each property:
- Abstract; The base class requires this property to be implemented but doesn't specify a value.
- Static; only store one value per type of implementation, instead of per object.

public interface IPiece
{
    readonly int Points;
    readonly char Letter;
}

public abstract class Piece
{
    public static readonly int Points;
    public static readonly char Letter;
}

public class King : Piece, IPiece
{
    public int Points = 0;
    public int Letter = 'K';
}

Upvotes: 1

Views: 1784

Answers (4)

Wouter
Wouter

Reputation: 2958

You should use a const or static readonly backingfield. (There are differences). Also the abstract class and the interface are redundant. Either let all your pieces derive from Piece or let them implement IPiece.

public interface IPiece
{
    int Points { get; }
    char Letter { get; }
}

public abstract class Piece : IPiece
{
    public abstract int Points { get; }
    public abstract char Letter { get; }
}

public class King : Piece
{
    public const int POINTS = 0;
    public const char LETTER = 'K';

    public override int Points { get { return POINTS; } }
    public override char Letter { get { return LETTER; } }
}

Note: Now still you cannot use the public const or static readonly in a very usefull way. Because you cannot reach the definition of the value without an instance. For example you cannot get the value of the King.LETTER when enumerating all values to determine what Piece to construct based on a character.

Upvotes: 0

Matthew Brubaker
Matthew Brubaker

Reputation: 3117

First, interfaces can have properties, but they can't have fields (as indicated in the comments on the question).

public interface IPiece
{
    int Points {get;} // readonly properties in interfaces must be defined like this
    char Letter {get;}
}

You also need to have your abstract class inherit from the interface in order for it to have access to the properties defined within it. Because it is an abstract class, you must mark the properties as abstract

public abstract class Piece : IPiece
{
    public abstract int Points {get;}
    public abstract char Letter {get;}
}

From there, you can create an implementation (King) of your abstract class (Piece). Since this is not an abstract implementation, you must provide implementations of the properties at this time.

public class King : Piece
{
    public override int Points {get; private set;} = 0;
    public override char Letter {get; private set;} = 'K';
}

Take a look here for further examples on property inheritance.

Upvotes: 1

mjwills
mjwills

Reputation: 23898

The standard pattern for solving this is:

public interface IPiece
{
    int Points { get; }
    char Letter { get; }
}

public class King : IPiece
{
    public int Points => 0;
    public char Letter => 'K';
}

There is no need to use static at all, since 0 and K are literals, and thus (like static) are effectively stored only once per class.

Note also that I have removed your abstract class - it is not useful as is since there is no logic in it. An abstract class without logic is conceptually equivalent to an interface (which you already have) so is unnecessary at this stage.

If you really want to use a static then you could use:

public class King : IPiece
{
    private static int points = 0;
    private static char letter = 'K';

    public int Points => points;
    public char Letter => letter;
}

but there is no major benefit to that.

Upvotes: 2

nemanja228
nemanja228

Reputation: 551

You cannot have a static abstract property. Static members of the class are not subject to polymorphism. If you wish to have a property defined in abstract class which should be shared by all implementations and you don't know it in compile-time, you can create a Singleton type for it, or a wrapper around if its not type defined in your code. Then you can have something like this:

public abstract class Piece // or interface
{
    public SingletonIntWrapper Points { get; }
    public SingletonCharWrapper Letter { get; }
}

Upvotes: 1

Related Questions