Related
Is the "programming to abstractions" principle in Clojure the same as duck typing? If not, what are the differences?
Here is a quote from http://www.braveclojure.com/core-functions-in-depth/:
The reason is that Clojure defines map and reduce functions in terms of the
sequence abstraction, not in terms of specific data structures. As
long as a data structure responds to the core sequence operations (the
functions first, rest, and cons, which we’ll look at more closely in a
moment), it will work with map, reduce, and oodles of other sequence
functions for free. This is what Clojurists mean by programming to
abstractions, and it’s a central tenet of Clojure philosophy.
I think of abstractions as named collections of operations. If you can
perform all of an abstraction’s operations on an object, then that
object is an instance of the abstraction. I think this way even
outside of programming. For example, the battery abstraction includes
the operation “connect a conducting medium to its anode and cathode,”
and the operation’s output is electrical current. It doesn’t matter if
the battery is made out of lithium or out of potatoes. It’s a battery
as long as it responds to the set of operations that define battery.
Data types are identified to be part of the abstract class by behaviour ("responds to"). Isn't this the essence of duck typing? Thanks for input.
Data types are identified to be part of the abstract class by behaviour ("responds to").
They're not, though. On the JVM, types can only be part of an interface if they explicitly state that they implement the interface, and then implement its methods. Merely implementing appropriately-named methods is not enough, as it is in, say, Python, a typical duck-typing language.
What's written is not exactly wrong, but it requires a bit of a specific viewpoint to interpret it as correct: you must realize that when the author writes,
As long as a data structure responds to the core sequence operations...
What is meant is that the type must implement the core sequence interfaces and their methods. In a way, merely exposing a function named first is not enough to "respond" to the same-named core sequence operation: the type must also implement the right interface in order to "respond". It's a weird way to write things in a VM that's not framed in terms of responding to messages, and requires some expertise and squinting to find a correct meaning in, but it's a reasonable simplification for beginners, who don't need to know about the details yet...unless they are inclined to ask Stack Overflow questions about duck typing!
Is the "programming to abstractions" principle in Clojure the same as
duck typing?
No.
Clojure is defined in terms of Extensible Abstractions.
These are Java interfaces ...
... which are used most prominently to define the core data
structures.
For example, the sequence abstraction is defined by clojure.lang.ISeq:
public interface ISeq extends IPersistentCollection {
Object first();
ISeq next();
ISeq more();
ISeq cons(Object o);
}
Any class that implements ISeq is accepted by Clojure as a sequence (whether is behaves properly is another matter). For example, lists and lazy sequences do so, and are treated impartially as sequences. Contrast this with classic Lisp, where a different set of functions apply to each.
And we have several different implementations of vectors
the core clojure vector type;
rrb vectors;
fast small vectors.
I could go on. (Actually, I can't. I don't know enough!)
I've found a question asking about the differences between class inclusion and class inheritance. What exactly does class inclusion mean? I don't think I've hear this term before ..
It's composition. Generally speaking, prefer composition over inheritance. Use inheritance to model only is-a-relationship (Liskov principle), not uses, dependencies or implemented-in-terms-of.
Think about your problem in terms of "is-a" and "has-a" (composition and inheritance). Please take a look at: Is-a and Has-a.
In short terms - if the class/object you're trying to implement "is" an instance of something more general, then it is an example of inheritance i.e.: Apple (derived class) is a Fruit (base class), Porsche is a Car etc.
If your object "has" or "is part of" something, then it is composition. Example: Car has an Engine (object of Engine is included in every Car object), House has Windows and Doors etc.
Whether you should use one or another is a topic for a different type of discussion. In general you want to prefer composition over inheritance as this allows for more flexible code.
Inclusion may have different treatments depending on the context:
InstanceOf/TypeOf relation describe the relationship between an instance and its class. In mathematics, it is membership relation (a member is included in its set). In the relational model, it is how tuples are members of relations.
General-specific relation among classes. In mathematics, it is subset relation which means that all members of a more specific set are also members of its more general set.
Object inclusion in prototype-based programming (like JavaScript). Here an object is included in its prototype object. Note however that it is not inclusion of classes and inheritance is implemented differently.
Concept inclusion in concept-oriented programming where concepts generalize classes and inclusion generalizes inheritance. In particularly, objects can share a super-object precisely as classes can share a super-class.
Composition. It is actually a different relation - not inclusion. Yet, it can be treated as inclusion under this assumption: composition object/class is a more specific element than an element it has. This assumption is one of the features of the concept-oriented model. It is a quite natural assumption which allows us to use composition for inheriting. One its advantage is that a super-object may have many extensions.
Containment relation. It is normally used to describe how instances are included in container objects (like Bad, Set etc.)
Inner classes.
One of the main conceptual differences of all forms of inclusion from inheritance is that inclusion assumes that many elements can be included in one (parent) element at the level of instances. In contrast, the classical inheritance (implicitly) assumes that an object may have only one extension. In other words, a super-object cannot be shared among many extensions.
Note again that it is probably not a complete list and there are significant overlaps between the above treatments as well as some incompatibilities.
There is a same concept for Strategy Pattern and Inheritance, so I can implement Strategy Pattern with Inheritance that sounds it is simpler and cleaner than Strategy Pattern.
Startegy Pattern:
class IBase
{
public:
virtual void processAction(void *data) = 0; // pure virtual
}
class Worker: public IBase
{
public:
virtual void processAction(void *data)
{
// define logic
}
}
Inheritance:
class Base
{
public:
virtual void processAction(void *data) {}
}
class Worker: public Base
{
public:
virtual void processAction(void *data) override
{
// define logic
}
}
My question is what is the difference between them? or when should I use Strategy Pattern or Inheritance?
Link: Strategy Pattern
Imagine you design a Cache. The cache can have options regarding
eviction policy (LIFO, FIFO, LRU)
expiration policy (after read, after write)
maximum size (number of elements, memory usage)
Now imagine you want to let the user of your cache choose any of these options, and you use inheritance. You'll need 3 * 2 * 2 = 12 different classes:
LifoAfterReadNumberOfElementsBasedCache,
LifoAfterReadMemoryBasedCache,
etc.
Each of the 4 LifoXxx classes will have to implement the same algorithm to implement the LIFO strategy. Same for the other ones.
Implement it with the strategy pattern instead of inheritance, and you'll have a single Cache class, and 7 strategy classes (one for each strategy), that you can combine however you want, and without code duplication.
And you can also let the user of your Cache define its own strategy, that you haven't anticipated, and let him combine it with other strategies without needing to create a whole lot of new subclasses.
Strategy is a pattern of OOP and Inheritance is a principle of OOP. Strategy is implemented using (or to support) Inheritance (actually, interface generalization).
Inheritance
Inheritance is used to achieve all benefits of OOP (it eventually
leads to better readbility\maintainability\structure of code).
Inheritance is used to form many other patterns, not only Strategy
Inheritance is sometimes a limitation because of its static compile-time nature
Strategy
Strategy assumes to have different implementations which can be replaced in runtime (or configured in a flexible way). So, your first example is not strategy as well.
In general, composition (which is implemented by Strategy) as a way of logic reuse is preferred over inheritance. At first, it provided dynamic polymorphism. At second, it has less implementation limitations like multi-class inheritance, etc.
Strategy corresponds to "some changeable algorithm" in terms of DDD, thus has real impact on domain modelling.
Strategy, as a pattern itself, provides a language ("pattern language") for communication between developers.
Moreover, according to your example:
Base abstract class and interface have two different semantics, thus inheritance in your example have different semantics too. First is about implementation of public contract. Second is about generalization as an extraction of common properties and methods.
The answer is in the Wikipedia article you linked in your question.
The strategy pattern uses composition instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time.
If your situation is simple and static, you certainly can use inheritance, but using Strategy allows you to better decouple complex code and allows simple switching between implementations of the strategy, even at run-time.
Examples may help. There are some good ones in the answers to this related question as well as in the other answers to your question.
A very real situation where you want the ability to change strategy at run-time is in sorting. The sort order can be varied by a strategy (commonly called a Comparator), and you can have multiple implementations of the strategy and mechanisms for the user of your program to change them.
If we are talking about Java, you can consider also the “Composition over inheritance” approach from Effective Java. This will help you with the method invocation, because inheritance violates encapsulation (in general perspective). By choosing composition you can extend your abstraction even further, because it provides you with the ground for Service instance you need.
Let me start with a concrete example. In C++, I have a hierarchy of classes under the abstract base class CollisionVolume. Any collision volume needs to be able to detectCollision with any other volume. This collision code is specialized based on the two subclasses in presence, but it is commutative: detectCollision(a, b) == detectCollision(b, a).
I need to use a mechanism similar to virtual functions since the objects will typically be of the abstract base class. However, if I use typical virtual methods, the chosen function can only depend on the type of one of the operand, not both. The only way I was able to do this is using RTTI or an RTTI-like mechanism.
Is there any cleaner way to do this?
You're looking for multiple dispatch. C++ doesn't have it because it's hard to implement efficiently. Most other statically typed/efficiency-oriented languages don't either. Your RTTI solution is probably about the best way of faking it.
There are several solutions to emulate multimethods in C++.
Here some references that can helps you to solve your problem:
S.Meyers "More effective C++", Item 31: Making functions virtual with respect to more than one object.
A.Alexandrescu "Modern C++ design", Chapter 11. Multimethods
MultiMethods in C++: Finding a complete solution by Danil Shopyrin
Multiple Dispatch. A new approach using templates and RTTI by Dr. Carlo Pescio, C++ Report, June 1998.
Draft proposal for adding Multimethods to C++, here and here
My initial idea, which upon reading appears to be the visitor pattern(?), is to make a virtual function that returns some vital information about the object, then, in detectCollision(), compare the vital information returned by the two objects. That way, each object can return specialized information, but they can be compared in a generalized way.
This may not be the most efficient way of doing it, but it seems relatively simple.
Isn’t a class with only static members a kind of singleton design pattern? Is there any disadvantage of having such a class? A detailed explanation would help.
This kind of class is known as a monostate - it is somewhat different from a singleton.
Why use a monostate rather than a singleton? In their original paper on the pattern, Bell & Crawford suggest three reasonns (paraphrased by me):
More natural access syntax
singleton lacks a name
easier to inherit from
I must admit, I don't find any of these particularly compelling. On the other hand, the monostate is definitely no worse than the singleton.
Robert C. Martin wrote an article some times ago about the differences between the mono state pattern and the singleton pattern.
Consider a family of Logging classes. They all implement "LogMessage(message, file, line_number). Some send messages to stderr, some send email to a set of developers, some increment the count of the particular message in a message-frequency table, some route to /dev/null. At runtime, the program checks its argument vector, registry, or environment variables for which Logging technique to use and instantiates the Logging Singleton with an object from a suitable class, possibly loading an end-user-supplied DLL to do so. That functionality is tough to duplicate with a pure static Singleton.
class with all static members/methods
a kind of singleton design pattern
Class - not pattern. When we talk about classes we can say class implements pattern.
Static functions - is not member functions, they are similar on global functions. Maybe you don't need any class?
Quote from wikipedia:
In software engineering, the singleton
pattern is a design pattern that is
used to restrict instantiation of a
class to one object.
By this definition your implementation is not singleton implementation - you don't use common idea One (or several in extended definition) instance of class.
But sometimes (not always) usage of class with all static functions and singleton pattern - not have meaningful difference.
For a singleton all constructors have to be private, so that you can access only through a function. But you're pretty close to it.