Reputation: 16669
In C#, is it possible to have an abstract parent class that declares a field of a type that itself corresponds to an abstract class and must be overridden in the child classes?
Here's the idea:
public abstract class AbstractInfo {
// ...
public GameplayResult gameplayResult;
}
public class LevelInfo : AbstractInfo {
// ...
public LevelGameplayResult gameplayResult;
}
public class BossInfo : AbstractInfo {
// ...
public BossGameplayResult gameplayResult;
}
With:
public abstract class GameplayResult {
// ...
}
public class LevelGameplayResult : GameplayResult {
// ...
}
public class BossGameplayResult : GameplayResult {
// ...
}
The goal is to be able to have another class:
public class Manager {
// ...
public AbstractInfo info;
public void UpdateInfo(GameplayResult gameplayResult) {
info.gameplayResult = gameplayResult;
// Where info could be a level info or boss info
// and gameplay result could be a level or boss gameplay result
}
}
Upvotes: 0
Views: 399
Reputation: 5261
There are a couple of issues in the example you've given.
gameplayResult
and thus redeclaring them. If you're looking for overriding a member, you need to use the override
keyword in the derived class and make the member abstract
or virtual
in the base class. Furthermore, a member field cannot be abstract, but you can use a property instead:public abstract class AbstractInfo
{
public abstract GameplayResult GameplayResult { get; set; }
}
public class LevelInfo : AbstractInfo
{
// Still something wrong here (see #2)
public override LevelGameplayResult GameplayResult { get; set; }
// For later demonstration...
public bool IAmLevelInfo { get; } = true;
}
Consider the example:
public void DoSomethingWithInfo(AbstractInfo info)
{
info.GameplayResult = new BossGameplayResult();
}
var lvlInf = new LevelInfo();
// Some time later...
DoSomethingWithInfo(lvlInfo);
if (!lvlInfo.IAmLevelInfo)
{
Console.WriteLine("How did this happen o.O")?
}
In the above example it should be completely legal to call DoSomethingWithInfo(lvlInfo)
because LevelInfo
is also an AbstractInfo
. Inside the method we're trying to assign a BossGameplayResult
to an AbstractInfo
's GameplayResult
which is completely legal. However, we passed in a LevelInfo
which does not allow you to assign a BossGameplayResult
to GameplayResult
. So we've hit a paradox. Of course, the above won't even compile, because the compiler is clever enough to realize this.
To solve this issue, you can use generics:
public abstract class AbstractInfo<T> where T : GameplayResult
{
public T GameplayResult { get; set; }
}
public class LevelInfo : AbstractInfo<LevelGameplayResult>
{
// No need for overriding, as 'GameplayResult' will
// have type 'LevelGameplayResult'
}
Upvotes: 1