Empty interfaces and abstract class enforce structure - c#

I've been looking into empty interfaces and abstract classes and from what I have read, they are generally bad practice. I intend to use them as the foundation for a small search application that I am writing. I would write the initial search provider and others would be allowed to create their own providers as well. My code's intent is enforce relationships between the classes for anyone who would like to implement them.
Can someone chime in and describe if and why this is still a bad practice and what, if any alternatives are available.
namespace Api.SearchProviders
{
public abstract class ListingSeachResult
{
public abstract string GetResultsAsJSON();
}
public abstract class SearchParameters
{
}
public interface IListingSearchProvider
{
ListingSeachResult SearchListings(SearchParameters p);
}
}

Empty classes and interfaces are generally only "usably useful" as generic constraints; the types are not usable by themselves, and generic constraints are generally the only context in which one may use them in conjunction with something else useful. For example, if IMagicThing encapsulates some values, some implementations are mutable, and some aren't, a method which wants to record the values associated with an IMagicThing might be written something like:
void RecordValues<T>(T it) where T:IImagicThing,IIsImmutable {...}
where IIsImmutable is an empty interface whose contract says that any class which implements it and reports some value for any property must forevermore report the same value for that property. A method written as indicated could know that its parameter was contractually obligated to behave as an immutable implementation of IMagicThing.
Conceptually, if various implementations of an interface will make different promises regarding their behaviors, being able to combine those promises with constraints would seem helpful. Unfortunately, there's a rather nasty limitation with this approach: it won't be possible to pass an object to the above method unless one knows a particular type which satisfies all of the constraints, and from which object derives. If there were only one constraint, one could cast the object to that type, but that won't work if there are two or more.
Because of the above difficulty when using constrained generics, it's better to express the concept of "an IMagicThing which promises to be immutable" by defining an interface IImmutableMagicThing which derives from IMagicThing but adds no new members. A method which expects an IImmutableMagicThing won't accept any IMagicThing that doesn't implement the immutable interface, even if it happens to be immutable, but if one has a reference to an IMagicThing that happens to implement IImmutableMagicThing, one can cast that reference to the latter type and pass it to a routine that requires it.
Incidentally, there's one other usage I can see for an empty class type: as an identity token. A class need not have any members to serve as a dictionary key, a monitor lock, or the target of a weak reference. Especially if one has extension methods associated with such usage, defining an empty class for such purpose may be much more convenient than using Object.

Related

Generic class with an interface constraint vs class implementing interface

Recently I was implementing a Trie data structure and decided the Nodes could store different types of data or have its implementation varied so then I went for Node<T>. Then as I got into the algorithm for constructing the Trie I realised it required more intimate knowledge of the Node so I constrained the generic class to use an INode interface. This allows for more flexibility but felt wrong in the context of a generic class.
Generic classes have a different use case to classes which implement an interface. For example, List<T> - the algorithm can work without being dependent on a related set of abstractions. A class which implements an interface may require polymorphism/DI but the interfaces will be more specialized.
Under what circumstances do others apply a generic class T where T may implement a more specialized interface?
I thought that a generic class is used when T does not really need to expose operations/data though I can see a generic class may be used where T implements IDisposable or some other more general interface.
Any help in clarifying these points?
When faced with a choice to use a generic with an interface constraint vs. a non-generic with an interface type, I would go for generic+interface only in situations when some or all of types passed as generic arguments are value types. This would prevent my implementation from requiring costly boxing and unboxing when dealing with my structs.
For example, if the interface happens to be IComparable, I wold definitely prefer a generic with a constraint, because it would let me avoid boxing when working with primitives.
Note that an alternative way of providing functionality to your generic class is passing a delegate along with the value. For example, if you plan to do something like this
interface IScoreable {
decimal GetScore(object context);
}
class Node<T> where T : IScoreable {
...
void DoSomething(T data) {
var score = data.GetScore(someContext);
...
}
}
you can also do this:
class Node<T> {
private Func<T,object,decimal> scorer;
public Node(Func<T,object,decimal> scorer) {
this.scorer = scorer;
}
...
void DoSomething(T data) {
var score = scorer(data, someContext);
...
}
}
The second solution lets you "decouple" the scoring functionality from the type being scored, at the expense of having the caller to write a little more code.
I see nothing wrong with placing constraints on the generic argument. Having a generic argument does not imply "this will work for anything", it implies that there is more than one way that the code will make sense.
It might actually expose a completely generic concept, like List<T>, but it might expose a concept that makes sense only in some contexts (like Nullable<T> only making sense for non-nullable entities)
The constraints are just that mechanism that you use to tell the world under what circumstances the class will make sense, and will enable you to actually use that (constrained) argument in a reasonable way, i.e. calling Dispose on things that implement IDisposable
The extreme of this is when the context is very constrained, i.e. what if there are only two possible implementations? I actually have that case in my current codebase, and I use generics. I need some processing done on some data point, and currently (and in the foreseeable future) there are only two kinds of data points. This is, in principle, the code I use:
interface IDataPoint
{
SomeResultType Process();
}
class FirstKindDataPoint : IDataPoint
{
SomeResultType Process(){...}
};
class SecondKindDataPoint : IDataPoint
{
SomeResultType Process(){...}
};
class DataPointProcessor<T> where T: IDataPoint
{
void AcquireAndProcessDataPoints(){...}
}
It makes sense, even in this constrained context, because I have only one processor, so only one logic to take care of, instead of two separate processor that I will have to try to keep in sync.
This way I can have a List<T> and an Action<T> within the processor instead of a List<IDataPoint> and Action<IDataPoint> which will be incorrect in my scenario, as I need a processor for a more specific data type, that is still, implementing IDataPoint.
If I needed a processor that will process anything, as long as it is an IDataPoint, it might make sense to remove the its genericity, and simply use IDataPoint within the code.
Additionally, the point raised in #dasblinkenlight's answer is very valid. If the generic parameters can be both structs and classes than using generics will avoid any boxing.
Generics are usually used where using an interface or a base class (and this includes object) are not enough, for example where you are worried about the return value's of your function being the original type rather than just the interface, or where the parameters you are passing in may be expressions that operate on the specific type.
So if you approach the logic from the other end. The decisions on type restrictions should be the same decision as when you are choosing the types of your function parameters.

How is polymorphysm look like by using Interfaces?

I don't get the connection of Interfaces To polymorphism.
Polymorphism for me is about executing a method in a different way for some different concrete classes using abstract methods or virtual methods+ overriding and therefore this is only linked to inheritance in my vision, but how do you override methods With Interfaces??
How do you use Interfaces for doing same method in different ways and giving the object to decide what to do according to its concrete type?
Thanks
As stated by Andreas Hartl in his article on Inheritance Vs. Interfaces:
Many high-level languages support inheritance and interfaces, and for
someone new to the concepts, it's sometimes not clear which one to
choose. Although languages differ in their exact handling of
inheritance and interfaces, the basics are usually the same, so this
tip should be valid for most languages.
Inheritance means that we derive one class (the derived class) from
another class (the base class). The derived class is an extension of
the base class. It contains all the features (methods and data
members) of the base class, can extend it with new features, and can
reimplement virtual methods of the base class. Some languages, like
C++, support multiple inheritance, where a derived class can have
multiple base classes, but usually inheritance is restricted to a
single base class.
Interfaces can usually only define methods and no data members (but C#
for example allows data members in the form of properties within
interfaces), and a class can always implement multiple interfaces. An
interface contains only method definitions without implementations,
and a class that implements an interface supplies the implementation.
So, using inheritance, you write a base class with method
implementations, and when you derive a class from it, this class will
inherit everything from the base class, and is immediately able to use
its features. An interface on the other hand is just a contract of
method signatures, and a class that wants to implement an interface is
forced to supply the implementations for all methods of the interface.
So when do you use which? In some cases, the language already dictates
what you use: if you need your class to have multiple 'parents', you
cannot use inheritance in languages that don't support multiple
inheritance. And if you want to reuse a library object, you have to
use the fitting concept, depending on if that library object is a
class or an interface.
But which to use if you are free to choose? Basically, base classes
describe and implement common behavior of related types, while
interfaces describe functionality that unrelated types can implement.
Inheritance describes 'is a' relationships, interfaces describe
'behaves like' relationships. For example, say that you are writing a
flight simulator. Your basic entity, which you will for example store
in a list, will be 'Airplane'. Your concrete types will be 'Concorde'
and 'Phantom'. So how should you model the three types? Concorde and
Phantom are related, they both are airplanes and share data, like
'Weight' or 'MaxSpeed' and functionality, like 'Accelerate', so we can
model them with inheritance. 'Airplane' will be the base class with
common data and methods, and 'Concorde' and 'Phantom' will derive from
'Airplane'. We could say that both are specialized airplanes, which is
why it's often said that inheritance means specialization. Now assume
that we also add a class 'Pilot' to our program, and we want to give
the user the ability to save the game and load it later. So when he
saves the game, we need to save the state of all Aircrafts and the
state of all Pilots. And we want to do this in one function that takes
just a list of all saveable objects. So how do we model this? To
answer this, we must take a look at the different types we want to
save. Pilots and Airplanes. It's obvious that they are not related at
all. They share no common data and no common functionality. We can see
that writing a base class 'Saveable' and derive both Pilot and
Airplane from it would make little sense, since no code in Saveable
could be reused by Airplane or Pilot, since both have no common
properties. In this case, an interface is the best solution. We can
write an interface 'ISaveable' with a method Save(). Pilot could then
implement ISaveable.Save() by saving his name, while Airplane could
save its current speed and coordinates.
As you can see, a clear image of the relationship between classes
often makes the choice clear: Use inheritance for related types, where
each derived class 'is a' base class. Use interfaces for unrelated
types which have some common functionality.
Here are some more points to consider with inheritance and interfaces:
Interfaces are fixed. When you change an interface, you have to change every class implementing that interface. But when you change a
base class, every derived class will gain the new functionality, which
can both be good (if you make a bugfix in some base class method
implementation, a derived class using that method will gain the bugfix
without you needing to change it) or bad (if a change in the baseclass
introduces a new bug, all derived classes using the method will be
bugged too).
Interfaces are usually more flexible, since in most languages you can only derive from one class, but implement many interfaces
Interfaces help to protect internal classes: Assume class A has an internal object b of class B. When a method in A returns a pointer or
reference to b, the code that called this method now has access to the
whole object b, which can be dangerous if A only wants to expose
certain members of b. This problem can be solved if you create an
interface I with just the members which are safe to expose. When B
implements this interface, and your method in A returns b via an I
pointer or reference, the outside code can only do what you allow
through the interface.
Polymorphism as a concept does not require inheritance, although in many languages inheritance is the only way to achieve it. Some languages, like smalltalk allow you to polymorphically use any type that implements the same set of members and properties. If it looks like a duck, quacks like a duck, and walks like a duck, you can treat it like a duck.
Polymorphism is simply the ability to treat one object as another object, by providing the same way to access and use it as the original object. This is best illustrated by the Liskov Substitution Principle. This is called the "Interface" or sometimes "Contract", because it defines a "signature" that another object can use to do interesting things to the object.
in C#, you can inherit from interfaces or other (non-sealed) classes. The difference is that an interface does not provide any actual storage or methods (only their "signature"), it is merely a definition. You can't instantiate an interface, you can only instantiate an object that implements an interface.
Classes implement an interface (IDisposable, for instance) in the same way you build a house based on blue prints. If you build two houses with the same blueprints, then each house has the exact same "interface", they may have different color paint, or carpeting, but they function in exactly the same way, yet they are two distinctly different houses, with many differences in how various things might function.
When it comes to C#, just know that an interface says what properties or members an object that implements it MUST have. Likewise, in C#, a big difference is that you can inherit multiple interfaces but only ever a single class. (ie public class Test : BaseClass, IDisposable, ITest, IFooBar)
consider this...
public int SomeMethod(SomeBaseClass object)
{
// Pass in a descendant classe that implements / overrides some method in SomebaseClass
}
public int SomeMethod(ISomeInterface intf)
{
// pass in concrete classes that implement some ISomeInterface function
}
This is the basic essence of polymorphic behavior, a common contract, implemented specifically by a specialist class.

Cast from something Generic of implementing to something Generic of interface type

probably a no-brainer, but please take a look at the following classes / Interfaces:
public interface IChallenge
public interface IChallengeView<T> where T : IChallenge
{
T Challenge {get;set;}
}
public interface IChallengeHostView
{
IChallengeView<IChallenge> ChallengeView { get; set; }
}
public class AdditionChallenge : IChallenge {}
public class AdditionChallengeView: IChallengeView<AdditionChallenge> {}
The scenario is a didactic app for young children.
I intend to keep the application flexible by separating the host (which could be any graphical surrounding) from the challenge that is to be solved. That way I could use the same surroundings to host addition, multiplication,division...
Now, when I want to fill this with some life, I get a conversion issue:
HostView hostView = new HostView(); // implements IChallengeHostView
AdditionChallengeView challengeView = new AdditionChallengeView();
hostView.ChallengeView = challengeView;
This, of course, does not work. I see why it doesn't but I have no clue whatsoever how to get around this.
Any ideas?
UPDATE : I had decided to post as little code as possible before, but that brought me into the trouble of hiding one issue from you guys: The interface IChallengeView has a settable property (now visible in the code above), which makes covariance impossible to apply here - The generic type parameter can only be invariant in that case.
The answer given by rich.okelly is correct, but based on false assumptions (which, again, were based on the poor level of detail given by my description here).
I decided to make the code a little less implementation-type-adhesive, like so:
public interface IChallenge
public interface IChallengeView
{
IChallenge Challenge {get;set;}
}
public interface IChallengeHostView
{
IChallengeView ChallengeView { get; set; }
}
public class AdditionChallenge : IChallenge {}
public class AdditionChallengeView: IChallengeView {}
That means I have some more casting code in the AdditionChallengeView (and all other implementing classes), but it seems to me that this is the only viable way at the time.
If you're using c#4 (or above) you can take advantage of variance. Try declaring your IChallengeView<T> interface as covariant like so:
public interface IChallengeView<out T> where T : IChallenge {}
It is often useful to separate out portions of an interface that use a type parameter in covariant fashion and those which use one i contravariant fashion. This often requires the use of a "SetProperty" method rather than a read-write property (for whatever reason, if an interface inherits an interface which includes a read-only property Foo, and another which implements a write-only property Foo, the compiler will say any attempts at property access are "ambiguous" and won't allow foo to be read or written, notwithstanding the fact that read accesses can only refer to the read-only property and write accesses to the write-only property. Nonetheless, separating out contravariant and covariant aspects of an interface will often allow one to use variance in the cases where it would be helpful and make sense. Further, separating out the portions of an interface which read an object is often helpful anyway.
One minor note: I would suggest that when using an interface one use the following terms to have the indicated meanings:
An a "readable" foo interface should provide a means for reading the characteristics of an object, but should make no promise about whether the object might be writable using some other other means.
A "read-only" foo interface should not only provide a means for reading the characteristics of an object, but should also promise that one may expose a reference to any legitimate implementation without exposing a means of writing to the object. There is no promise, however, that there isn't some some other means by which the object might be modified.
An "immutable" foo interface should promise that any property which is observed to have a given value will always have that value.
If code needs to simply read out what's in an object, it can ask for an "IReadableFoo". If code is using an object reference for short-term encapsulation data which it wants to expose to other code, but isn't allowed to expose the object itself to anything that might modify it, it should wrap the object in a read-only wrapper unless it can safely expose the object directly (which would be indicated by the object implementing IReadOnlyFoo. If code wants to persist a reference as a means of persisting a snapshot of the data therein, it should make a copy of the object if there's any possibility that it might change, but shouldn't bother if the object will always be the same (indicated by IImmutableFoo).

Why do we need to have Object class as baseclass for all the classes?

Either in C# or Java or in any other language which follows oops concepts generally has 'Object' as super class for it by default. Why do we need to have Object as base class for all the classes we create?
When multiple inheritance is not possible in a language such as C# or Java how can we derive our class from another class when it is already derived from Object class. This question may look like silly but wanted to know some experts opinions on it.
Having a single-rooted type hierarchy can be handy in various ways. In particular, before generics came along, it was the only way that something like ArrayList would work. With generics, there's significantly less advantage to it - although it could still be useful in some situations, I suspect. EDIT: As an example, LINQ to XML's construction model is very "loose" in terms of being specified via object... but it works really well.
As for deriving from different classes - you derive directly from one class, but that will in turn derive indirectly from another one, and so on up to Object.
Note that the things which "all objects have in common" such as hash code, equality and monitors count as another design decision which I would question the wisdom of. Without a single rooted hierarchy these design decisions possibly wouldn't have been made the same way ;)
The fact that every class inherits object ensured by the compiler.
Meaning that is you write:
class A {}
It will compile like:
class A : Object{}
But if you state:
class B : A {}
Object will be in the hierarchy of B but not directly - so there is still no multiple inheritance.
In short
1) The Object class defines the basic state and behavior that all objects must have, such as the ability to compare oneself to another object, to convert to a string, to wait on a condition variable, to notify other objects that a condition variable has changed, and to return the object's class.
2) You can have B extend C, and A extend B. A is the child class of B, and B is the child class of C. Naturally, A is also a child class of C.
Well, the multiple inheritance of Object does not apply - you can think of it as:
"If a type doesn't have a base type, then implicitly inject Object".
Thus, applying the rule ad-nauseam, all types inherit from object once and once only - since at the bottom of the hierarchy must be a type that has no base; and therefore which will implicitly inherit from Object.
As for why these languages/frameworks have this as a feature, I have a few reasons:
1) The clue's in the name 'Object Oriented'. Everything is an object, therefore everything should have 'Object' (or equivalent) at it's core otherwise the design principle would be broken from the get-go.
2) Allows the framework to provide hooks for common operations that all types should/might need to support. Such as hash-code generation, string output for debugging etc etc.
3) It means that you can avoid resorting to nasty type casts that can break stuff - like (((int *)(void*))value) - since you have a nice friendly supertype for everything
There's probably loads more than this - and in the time it's taken me to write this 6 new answers have been posted; so I'll leave it there and hope that better people than I can explain in more detail and perhaps better :)
Regarding the first part of your question, it's how classes receive common properties and methods. It's also how we can have strongly-typed parameters to functions that can accept any object.
Regarding your second question, you simply derive your class from the other class; it will then be a descendant of that class, which is in turn a descendant of Object. There's no conflict.
You have the Object base class because amongst others because the Object class has methods (like, in .NET, GetHashCode(), which contain common functionality every object should have).
Multiple inheritance is indeed not possible, but it is possible to derive class A from class B, because A may not directly derive from Object, but B does, so all classes ultimately derive from Object, if you go far enough in the class' inheritance hierarchy.
Just to compare, let's take a look at a language that doesn't enforce a single root class - Objective-C. In most Objective-C environments there will be three root classes available (Object, NSObject and NSProxy), and you can write your own root class by just not declaring a superclass. In fact Object is deprecated and only exists for legacy reasons, but it's informative to include it in this discussion. The language is duck typed, so you can declare a variable's type as "any old object" (written as id), then it doesn't even matter what root class it has.
OK, so we've got all of these base classes. In fact, even for the compiler and runtime libraries to be able to get anywhere they need some common behaviour: the root classes must all have a pointer ivar called isa that references a class definition structure. Without that pointer, the compiler doesn't know how to create an object structure, and the runtime library won't know how to find out what class an object is, what its instance variables are, what messages it responds to and so forth.
So even though Objective-C claims to have multiple root classes, in fact there's some behaviour that all objects must implement. So in all but name, there's really a common primitive superclass, albeit one with less API than java.lang.Object.
N.B. as it happens both NSObject and NSProxy do provide a rich API similar to java.lang.Object, via a protocol (like a Java interface). Most API that claims to deal with the id type (remember, that's the "any old object" type) will actually assume it responds to messages in the protocol. By the time you actually need to use an object, rather than just create it with a compiler, it turns out to be useful to fold all of this common behaviour like equality, hashing, string descriptions etc. into the root class.
Well multiple inheritance is a totally different ball game.
An example of multiple inheritance:-
class Root
{
public abstract void Test();
}
class leftChild : Root
{
public override void Test()
{
}
}
class rightChild : Root
{
public override void Test()
{
}
}
class leafChild : rightChild, leftChild
{
}
The problem here being leafChild inherits Test of rightChild and leftChild. So a case of conflicting methods. This is called a diamond problem.
But when you use the object as super class the hierarchy goes like this:-
class Object
{
public abstract void hashcode();
//other methods
}
class leftChild : Object
{
public override void hashcode()
{
}
}
class rightChild : Object
{
public override void hashcode()
{
}
}
So here we derive both classes from Object but that's the end of it.
It acts like a template for all the objects which will derive from it, so that some common functionality required by every object is provided by default. For example cloning, hashcode and object locking etc.

C#: Specify that a function arg must inherit from one class, and implement an interface?

I'm making a game where each Actor is represented by a GameObjectController. Game Objects that can partake in combat implement ICombatant. How can I specify that arguments to a combat function must inherit from GameObjectController and implement ICombatant? Or does this indicate that my code is structured poorly?
public void ComputeAttackUpdate(ICombatant attacker, AttackType attackType, ICombatant victim)
In the above code, I want attacker and victim to inherit from GameObjectController and implement ICombatant. Is this syntactically possible?
I'd say it probably indicates you could restructure somehow, like, have a base Combatant class that attacker and victim inherit from, which inherits from GameObjectController and implements ICombatant.
however, you could do something like
ComputeAttackUpdate<T,U>(T attacker, AttackType attackType, U victim)
where T: ICombatant, GameObjectController
where U: ICombatant, GameObjectController
Although I probably wouldn't.
Presumably all ICombatants must also be GameObjectControllers? If so, you might want to make a new interface IGameObjectController and then declare:
interface IGameObjectController
{
// Interface here.
}
interface ICombatant : IGameObjectController
{
// Interface for combat stuff here.
}
class GameObjectController : IGameObjectController
{
// Implementation here.
}
class FooActor : GameObjectController, ICombatant
{
// Implementation for fighting here.
}
It is only syntactically possible if GameObjectController itself implements ICombatant; otherwise, I would say you have a design problem.
Interfaces are intended to define the operations available on some object; base classes identify what that object is. You can only pick one or the other. If accepting the ICombatant interface as an argument is not sufficient, it might indicate that ICombatant is defined too narrowly (i.e. doesn't support everything you need it to do).
I'd have to see the specifics of what you're trying to do with this object in order to go into much more depth.
What if you did this instead:
public class GameObjectControllerCombatant : GameObjectController, ICombatant
{
// ...
}
Then derive your combatant classes from this instead of directly from GameObjectController. It still feels to me like it's breaking encapsulation, and the awkwardness of the name is a strong indication that your combatant classes are violating the Single Responsibility Principle... but it would work.
Well, sort of. You can write a generic method:
public void ComputeAttackUpdate<T>(T attacker, AttackType type, T victim)
where T : GameObjectController, ICombatant
That means T has to satisfy both the constraints you need. It's pretty grim though - and if the attacker and victim could be different (somewhat unrelated) types, you'd have to make it generic in two type parameters instead.
However, I would personally try to go for a more natural solution. This isn't a situation I find myself in, certainly. If you need to regard an argument in two different ways, perhaps you actually want two different methods?
If you control all the classes in question, and if GameObjectController doesn't define any fields, the cleanest approach would be to define an IGameObjectController (whose properties and methods match those of GameObjectController) and an ICombatantGameObjectContoller (which derives from both IGameObjectController and ICombatant). Every class which is to be usable in situations that require both interfaces must be explicitly declared as implementing ICombatantGameObjectController, even though adding that declaration wouldn't require adding any extra code. If one does that, one can use parameters, fields, and variables of type ICombatantGameObjectController without difficulty.
If you can't set up your classes and interfaces as described above, the approach offered by Jon Skeet is a generally good one, but with a nasty caveat: to call a generic function like Mr. Skeet's ComputeAttackUpdate, the compiler has to be able to determine a single type which it knows is compatible with the type of the object being passed in and with all of the constraints. If there are descendants of GameObjectController which implement ICombatant but do not derive from a common base type which also implements GameObjectController, it may be difficult to store such objects in a field and later pass them to generic routines. There is a way, and if you need to I can explain it, but it's a bit tricky.

Categories

Resources