I'm trying to create a (rather clumsy) little game and I've come to a problem.
I have a class tree as follows:
Entity
Character
Player
Enemy
Static
Stairs
OtherEncounter
Now I intend to implement a generator which should generate a map based on some simple heuristics and via Entity constructor add encounters to some Tiles. For that I chose to use "Entity e" parameter in my Tile contructor.
Now for getting the correct type I set up a virtual method in all classes to return their exact type. That being abstract both in Entity.cs and Character.cs. But as expected, it doesn't do much good to inherit an abstract method and make it abstract again.
Thus, my question is, is there any kind of "correct" implementation or is there just some simple workaround? I could always just skip the method in Entity.cs and create two distinct in both Character.cs and Static.cs, but that just seems too... redneck-y.
TL;DR: How to inherit abstract method in grandchildren while not declaring in children.
Assuming Character is abstract, you don't have to implement it in Character at all. See this example:
public abstract class Parent
{
public abstract string Name {get;}
}
public abstract class Child : Parent
{
}
public class Grandchild: Child
{
public override string Name { get { return "Test"; } }
}
Because Child is also abstract, you don't need to redeclare any methods as abstract, so it just passes the implementation requirement onto Grandchild.
Try it online
Related
The C# spec, section 10.1.1.1, states:
An abstract class is permitted (but
not required) to contain abstract
members.
This allows me to create classes like this:
public abstract class A
{
public void Main()
{
// it's full of logic!
}
}
Or even better:
public abstract class A
{
public virtual void Main() { }
}
public abstract class B : A
{
public override sealed void Main()
{
// it's full of logic!
}
}
This is really a concrete class; it's only abstract in so far as one can't instantiate it. For example, if I wanted to execute the logic in B.Main() I would have to first get an instance of B, which is impossible.
If inheritors don't actually have to provide implementation, then why call it abstract?
Put another way, why does C# allow an abstract class with only concrete members?
I should mention that I am already familiar with the intended functionality of abstract types and members.
Perhaps a good example is a common base class that provides shared properties and perhaps other members for derived classes, but does not represent a concrete object. For example:
public abstract class Pet
{
public string Name{get;set;}
}
public class Dog : Pet
{
public void Bark(){ ... }
}
All pets have names, but a pet itself is an abstract concept. An instance of a pet must be a dog or some other kind of animal.
The difference here is that instead of providing a method that should be overridden by implementors, the base class declares that all pets are composed of at least a Name property.
The idea is to force the implementor to derive from the class as it is intended to provide only a basis for a presumably more specialized implementation. So the base class, while not having any abstract members may only contain core methods an properties that can be used as a basis for extension.
For example:
public abstract class FourLeggedAnimal
{
public void Walk()
{
// most 4 legged animals walk the same (silly example, but it works)
}
public void Chew()
{
}
}
public class Dog : FourLeggedAnimal
{
public void Bark()
{
}
}
public class Cat : FourLeggedAnimal
{
public void Purr()
{
}
}
I think a slightly more accurate representation of your question would be: Why does C# allow an abstract class with only concrete members?
The answer: There's no good reason not to. Perhaps someone out there has some organizational structure where they like to have a noninstantiatable class at the top, even if a class below it just inherits and adds nothing. There's no good reason not to support that.
You said it -- because you can't instantiate it; it is meant to be a template only.
It is not "really a concrete class" if you declare it as abstract. That is available to you as a design choice.
That design choice may have to do with creating entities that are (at risk of mixing the terminology) abstractions of real-world objects, and with readability. You may want to declare parameters of type Car, but don't want objects to be declarable as Car -- you want every object of type Car to be instantiated as a Truck, Sedan, Coupe, or Roadster. The fact that Car doesn't require inheritors to add implementation does not detract from its value as an abstract version of its inheritors that cannot itself be instantiated.
Abstract means providing an abstraction of behaviour. For example Vehicle is an abstract form. It doesn't have any real world instance, but we can say that Vehicle has accelerating behaviour. More specifically Ford Ikon is a vehicle, and Yamaha FZ is a vehicle. Both these have accelerating behaviour.
If you now make this in the class form. Vehicle is abstract class with Acceleration method. While you may/ may not provide any abstract method. But the business need is that Vehicle should not be instantiated. Hence you make it abstract. The other two classes - Ikon and FZ are concrete classes deriving from Vehicle class. These two will have their own properties and behaviours.
With regards to usage, using abstract on a class declaration but having no abstract members is the same as having the class public but using protected on its constructors. Both force the class to be derived in order for it to be instantiated.
However, as far as self-documenting code goes, by marking the class abstract it informs others that this class is never meant to be instantiated on its own, even if it has no virtual or abstract members. Whereas protecting the constructors makes no such assertion.
The compiler does not prevent implementation-logic, but in your case I would simply omit abstract ?! BTW some methods could be implemented with { throw Exception("must inherit"); } and the compiler could not distinguish fully implemented classes and functions including only throw.
Here's a potential reason:
Layer Supertype
It's not uncommon for all the objects
in a layer to have methods you don't
want to have duplicated throughout the
system. You can move all of this
behavior into a common Layer
Supertype.
-- Martin Fowler
There's no reason to prevent having only concrete methods in an abstract class - it's just less common. The Layer Supertype is a case where this might make sense.
I see abstract classes serving two main purposes:
An incomplete class that must be specialized to provide some concrete service. Here, abstract members would be optional. The class would provide some services that the child classes can use and could define abstract members that it uses to provide its service, like in the Template Method Pattern. This type of abstract class is meant to create an inheritance hierarchy.
A class that only provides static utility methods. In this case, abstract members don't make sense at all. C# supports this notion with static classes, they are implicitly abstract and sealed. This can also be achieved with a sealed class with a private constructor.
For example, say I wanted to create a class that inherits System.Diagnostics.StopWatch, and for this example pretend that System.Diagnostics.Stopwatch.StartNew() is the only public constructor for that class (I know its not, but I'm trying to inherit a different class where that is the case) :
public class Example : System.Diagnostics.Stopwatch
{
public Example()
{
// ... return System.Diagnostics.Stopwatch.StartNew();
}
}
I know there are obvious workarounds, but just wondering if this is possible in C#
There are basically three scenarios where you can't inherit from a class:
The intended parent class is declared as sealed, which prohibits inheriting from it.
The intended parent class doesn't have an accessible constructor.
The intended parent class is a static class.
If you are in one of these 3 scenarios, you will not be able to inherit from that class, plain and simple, don't look for a usable workaround because there isn't.
Is there a way that a derived class could inherit only a few of all the base class members..in C#?
If such maneuver is possible, please provide some example code.
Is there a way that a derived class could inherit only a few of all the base class members..in C#?
Yes. Make a base class that has one method, one constructor and one destructor. It has three new members, plus the heritable members of its base class. Now derive a class from that. The constructor and destructor will not be inherited; all the other members will. Therefore it is possible to create a derived class which inherits only some of its base class's members.
I suspect that answer is unsatisfying.
If your question is actually "is there a way that a base class can restrict what heritable members are inherited by a derived class?" the answer is no. Derived classes inherit all heritable members of base classes, regardless of their accessibility.
If your question is "is there a way that a derived class can choose which heritable members to inherit from a base class?" the answer is no. Derived classes inherit all heritable members of base classes, regardless of their accessibility.
Further reading, if this topic interests you:
https://ericlippert.com/2011/09/19/inheritance-and-representation/
When you make a type inherit from another, you get everything - both the good and the "bad" bits from the parent type ("bad", in this context, meaning something you didn't want to have).
You can hide something from the parent class in the child class through the new modifier. However, take this advice from years of experience... More often than not this leads to a lot of work being spent on doing workarounds in the way the child class works. You'll spare yourself from a lot of trouble if instead of going this way, you redesign your classes.
If a child type has to clip off functionalities from a parent type, you probably have a design flaw in the parent. Reshape it to have less funcionality. You can have its different features redistributed among different children. A class doesn't always have to be an only child, you know ;)
No, it's not possible. Do you imagine a Cat deriving Animal and the child (the Cat) deciding what's interesting from animals or not? A cat is an animal and this can't be changed.
BTW, interfaces can be used to hide details. For example:
public interface ISome
{
string Text { get; set; }
}
public class A : ISome
{
public string Text { get; set; }
public string Text2 { get; set; }
}
public class B : A
{
}
// This is an upcast. You're reducing the typing of an instance of B
ISome a = new B();
string text2 = a.Text2; // Error, Text2 isn't a property of ISome
string text = a.Text; // OK, Text is a property of ISome
What are the cons/risks of base class implementing an interface?
Is it better to always implement an interface on the sub-class?
When would you use one or the other?
public interface IFriendly
{
string GetFriendly();
}
public abstract class Person: IFriendly
{
public abstract string GetFriendly();
}
VS.
public interface IFriendly
{
string GetFriendly();
}
public abstract class Person
{
// some other stuff i would like subclasses to have
}
public abstract class Employee : Person, IFriendly
{
public string GetFriendly()
{
return "friendly";
}
}
Well, you need to think of it that way:
public interface IBreathing
{
void Breathe();
}
//because every human breathe
public abstract class Human : IBreathing
{
abstract void Breathe();
}
public interface IVillain
{
void FightHumanity();
}
public interface IHero
{
void SaveHumanity();
}
//not every human is a villain
public class HumanVillain : Human, IVillain
{
void Breathe() {}
void FightHumanity() {}
}
//but not every is a hero either
public class HumanHero : Human, IHero
{
void Breathe() {}
void SaveHumanity() {}
}
The point is that you base class should implement interface (or inherit but only expose its definition as abstract) only if every other class that derives from it should also implement that interface.
So, with basic example provided above, you'd make Human implement IBreathing only if every Human breaths (which is correct here).
But! You can't make Human implement both IVillain and IHero because that would make us unable to distinguish later on if it's one or another. Actually, such implementation would imply that every Human is both a villain and hero at once.
To wrap up answers to your question:
What are the cons/risks of base class implementing an interface?
None, if every class deriving from it should implement that interface too.
Is it better to always implement an interface on the sub-class?
If every class deriving from base one should also implement that interface, it's rather a must
When would you use one or the other?
If every class deriving from base one should implement such interface, make base class inherit it. If not, make concrete class implement such interface.
Starting with a base class ties you to the implementation of the base class. We always start off thinking the base class is exactly what we want. Then we need a new inherited class and it doesn't quite fit, so we find ourselves going back and modifying the base class to fit the needs of the inherited class. It happens all the time.
If you start with an interface then you have a little more flexibility. Instead of having to modify the base class you can just write a new class that implements the interface. You can have the benefit of class inheritance when it works, but you're not tied to it when it doesn't work.
I loved class inheritance when I first started with OOP. What's surprising is how infrequently it ends up being practical. That's where the principal of Composition Over Inheritance comes in. It's preferable to build functionality out of combinations of classes rather than having it nested inside inherited classes.
There's also the Open/Closed principle. If you can inherit, great, but you don't want to have to go back and change the base class (and risk breaking other stuff) because it's needed for a new inherited class to work right. Programming to an interface instead of a base class can protect you from having to modify existing base classes.
I've got a question about accidentally hiding abstract methods.
I'm creating a basic Entity class as an interface from which to create all other entities in the game I'm working on.
From this Entity class, I have created several derived classes. There are things like MovingEntity, Trigger, Door, etc... Many of these children classes also have children derived from them. For example, MovingEntity has classes like Projectile and EnemyUnit as children.
In my base Entity class, I have methods like Update() and Render() that are abstract, because I want every entity to implement these methods.
Once I get down to the second level, however, -that's- where I hit my question/problem. I'll use the Trigger class, for example. Trigger derives from the base Entity class, but Trigger still has its own children (like TriggerRespawning and TriggerLimitedLifetime). I don't want to instantiate a Trigger object, so I can keep that class abstract - I will only create objects from Trigger's children classes. But what do I do with the abstract methods that Trigger is supposed to implement from Entity?
I thought I could just basically use the same code in Trigger as I did in Entity. Declare the same method, same name, same parameters, and just call it abstract. Then, Trigger's children would be forced to implement the actual functions.
This didn't work, however, because in the Trigger class, my build errors say that I am hiding the abstract methods from the base Entity class.
How can I pass down the idea of forcing the eventual children to implement these abstract methods without making all of the parents in-between implement them? Do I need to use virtual on the first round of children classes?
I haven't been able to find a good answer on this so far, so I decided to break down and ask. Thanks in advance, guys.
Just don't redeclare the methods at all - the eventual concrete classes will have to implement all the abstract methods still unimplemented all the way up the tree:
public abstract class Foo
{
public abstract int M();
}
public abstract class Bar : Foo
{
// Concrete methods can call M() in here
}
public class Baz : Bar
{
public override int M() { return 0; }
}