Reputation: 5116
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
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
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
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
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