In Crystal, what's the difference between inheritance and inclusion? - crystal-lang

In most of the Crystal docs, class inheritance is used, with < syntax (e.g. https://stackoverflow.com/a/61053311/2954547).
However, HTTP::Handler says that custom handlers must include the HTTP::Handler module and not inherit from some class.
I can't find a description in the Crystal docs of what include-ing a module is supposed to do, or how it differs from <-inheritance of classes.
What does it mean when a class includes a module?

Inclusion is also a form of inheritance.
The main difference is really that extending a type is limited to exactly one parent. The extension inheritance graph of the entire program is a tree.
In contrast, a type can include multiple modules. And there can be multiple include inheritance paths between two types.

The description of inclusion is buried in the "Module" specification: https://crystal-lang.org/reference/syntax_and_semantics/modules.html
The example in the docs page is:
An include makes a type include methods defined in that module as instance methods:
module ItemsSize
def size
items.size
end
end
class Items
include ItemsSize
def items
[1, 2, 3]
end
end
items = Items.new
items.size # => 3
There is also the related extend, which includes module members as class-level members and not instance-level members.
This is a useful way to define mixins or other namespaces, that are not meant to be instantiated as objects.

Related

Inheritance and Includes

Lets say I have 2 classes. One is BaseClass and one is DerivedClass, being a derived class of BaseClass. I need to be able to create objects of both classes in another file. By using an #include statement to include the derived class in the new file, I have access to the derived class directly and the base class indirectly (as the derived class includes it in its file). Is it better to use this method of indirect "access" to the base class, or would it be better to directly include it alongside the derived class in the file?
The general advice is include what you use.
If you are coding to an API specification, and that specification does not explicitly detail the base-derived nature of the classes, then any changes to that relationship may break the includes that the files you depend on use.
See here as well.
If you are certain the BaseClass will always the base to the DerivedClass, then there may be little need include both, but for clarity, I would go ahead and do it anyway, it shows your intent.
Including all needed headers instead of relying on transitivity gives has two advantages:
If your header files will be refactored, you will not need to change your cpp file.
It clearly identifies your intent for other developers.

How to represent the nested class of C++ in UML?

How to represent the nested class of C++ in UML?
class A {
class B {
}
}
Nested class in UML (for any language) can be represented as:
Here
Class Inner1 is nested inside the outer class Outer 1
Classes Inner2, Inner3, Inner4 classes are nested inside Outer2
Reference taken from here
I had thought that the spec got away from the cross-and-circle notation. So, I did some wandering around in the specs, and couldn't find it in 2.0. I have to conclude that the 2.0 spec no longer supports it. While it's actually specified in v1.4, I looked all through the 2.4.1 spec, and it isn't anywhere to be seen (in fact, the word "anchor" returns 0 results in a document-wide search). I did some other looking around, and here's what I can piece together.
First, I had always understood that nested classes were a means of implementing composition. Furthermore, UML attempts to be implementation-agnostic, and nested classes aren't. (You can create composition in other ways, and not all OO languages support nested classes.) Now, 1.4's explanation includes this:
If Class B is attached to Class A by an “anchor” line with the “anchor” symbol on Class A, then Class B is declared within the Namespace of Class A. That is, the relationship between Class A and Class B is the namespace-ownedElement association.
Ok. Now UML 2.0 says this:
Kernel package represents the core modeling concepts of the UML, including classes, associations, and packages.
Here is a diagram of the Kernel package:
That's pretty abstruse, but have a look at the NamedElement abstract class at the top left. (A "NamedElement" class is an element that has a name.) Notice that Namespace derives from it. Now, notice on the right, directly to the right of the top of the Namespace class, there's another NamedElement class. One of the associations has the {subsets ownedElement} property on it, and a composition diamond on the Namespace end. On the Namespace end, there is the {subsets owner} property.
This means that NamedElement, when in composition association with Namespace, is a subset of Namespace. In other words, the relationship between Namespace and NamedElement is the namespace-ownedElement association described in the 1.4 spec. Therefore, the composition relationship, when adorned with the namespace and ownedElement properties, represents a nested (or inner, or internal, or whatever your favorite coding language calls it) class.
So, I'm going to say that this is the accepted 2.0 way to show nested classes if you are using composition notation. Like this:
Now, another way is to stick the nested class inside the containing class. The notation examples in the spec don't show this AFAICS, but they show it with other NamedElements (packages, components, etc.) so I don't see why you can't.
However, I don't see that the anchor notation is current. xmojmr's favorite site (and a good site, too), www.uml-diagrams.org, has this to say about it:
Now obsolete UML 1.4.2 Specification defined nested class as a class declared within another class and belonging to the namespace of the declaring class. Relationship between those classes was called "namespace owned element association
Nested classifier, e.g. nested class, nested interface, or nested use case could be used like any other classifier but only inside the containing class or interface.
Per UML 1.4.2 a declaring (nesting) class and a nested class could be shown connected by a line, with an "anchor" icon on the end connected to the declaring class. An anchor icon is a cross inside a circle.
UML 2.x specifications - including the recent UML 2.4.1 - describe nesting of classifiers within structured classes without providing explicit notation for the nesting. Note, that UML's 1.4 "anchor" notation is still used in one example in UML 2.4.x for packages as an "alternative membership notation" and without providing any other details or explanations.
I couldn't find that "one example" diagram, so maybe it's still around. But at the very least, the notation seems to be deprecated. I would either use the properties, create a <<nested>> stereotype, or put the nested class inside the owner class.
Nested classes may be displayed inside a compartment of the outer class.
Section 9.2.4.1 of the UML version 2.5.1 specification says:
If a Classifier has ownedMembers that are Classifiers, a conforming tool may provide the option to show the owned Classifiers, and relationships between them, diagrammatically nested within a separate compartment of the owning Classifier’s rectangle. (...) For example, a compartment showing the contents of the property nestedClassifier for a Class (see 11.4.2) shall be called “nested classifiers”.
Alternatively, nested classes may be displayed using the "circle-plus" notation:
Section 7.4.4.1 of the UML 2.5.1 specification says:
Conforming tools may optionally allow the “circle-plus” notation defined in sub clause 12.2.4 to show Package membership to also be used to show membership in other kinds of Namespaces (for example, to show nestedClassifiers).
(I have copied the image from the answer posted by #stamhaney)

Module and Class in OCaml

What are the differences between Module and Class in OCaml.
From my searching, I found this:
Both provide mechanisms for abstraction and encapsulation, for
subtyping (by omitting methods in objects, and omitting fields in
modules), and for inheritance (objects use inherit; modules use
include). However, the two systems are not comparable.
On the one hand, objects have an advantage: objects are first-class
values, and modules are not—in other words, modules do not support
dynamic lookup. On the other hand, modules have an advantage: modules
can contain type definitions, and objects cannot.
First, I don't understand what does "Modules do not support dynamic lookup" mean. From my part, abstraction and polymorphism do mean parent pointer can refer to a child instance. Is that the "dynamic lookup"? If not, what actually dynamic lookup means?
In practical, when do we choose to use Module and when Class?
The main difference between Module and Class is that you don't instantiate a module.
A module is basically just a "drawer" where you can put types, functions, other modules, etc... It is just here to order your code. This drawer is however really powerful thanks to functors.
A class, on the other hand, exists to be instantiated. They contains variables and methods. You can create an object from a class, and each object contains its own variable and methods (as defined in the class).
In practice, using a module will be a good solution most of the time. A class can be useful when you need inheritance (widgets for example).
From a practical perspective dynamic lookup lets you have different objects with the same method without specifying to which class/module it belongs. It helps you when using inheritance.
For example, let's use two data structures: SingleList and DoubleLinkedList, which, both, inherit from List and have the method pop. Each class has its own implementation of the method (because of the 'override').
So, when you want to call it, the lookup of the method is done at runtime (a.k.a. dynamically) when you do a list#pop.
If you were using modules you would have to use SingleList.pop list or DoubleLinkedList.pop list.
EDIT: As #Majestic12 said, most of the time, OCaml users tend to use modules over classes. Using the second when they need inheritance or instances (check his answer).
I wanted to make the description practical as you seem new to OCaml.
Hope it can help you.

Is there a usecase for nested classes?

I've recently seen several people doing things like this here on Stackoverflow:
class A:
foo = 1
class B:
def blah(self):
pass
In other words, they have nested classes. This works (although people new to Python seem to run into problems because it doesn't behave like they thought it would), but I can't think of any reason to do this in any language at all, and certainly not in Python. Is there such a usecase? Why are people doing this? Searching for this it seems it's reasonably common in C++, is there a good reason there?
The main reason for putting one class in another is to avoid polluting the global namespace with things that are used only inside one class and therefore doesn't belong in the global namespace. This is applicable even to Python, with the global namespace being a namespace of a particular module. For example if you have SomeClass and OtherClass, and both of them need to read something in a specialized way, it is better to have SomeClass.Reader and OtherClass.Reader rather than SomeClassReader and OtherClassReader.
I have never encountered this in C++, though. It can be problematic to control access to the outer class' fields from a nested class. And it is also pretty common to have just one public class in a compilation unit defined in the header file and some utility classes defined in the CPP file (the Qt library is a great example of this). This way they aren't visible to "outsiders" which is good, so it doesn't make much sense to include them in the header. It also helps to increase binary compatibility which is otherwise a pain to maintain. Well, it's a pain anyway, but much less so.
A great example of a language where nested classes are really useful is Java. Nested classes there automatically have a pointer to the instance of the outer class that creates them (unless you declare the inner class as static). This way you don't need to pass "outer" to their constructors and you can address the outer class' fields just by their names.
It allows you to control the access of the nested class- for example, it's often used for implementation detail classes. In C++ it also has advantages in terms of when various things are parsed and what you can access without having to declare first.
I am not a big fan of python, but to me this type of decisions are more semantical than syntactical. If you are implementing a list, the class Node inside List is not a class in itself meant to be used from anywhere, but an implementation detail of the list. At the same time you can have a Node internal class inside Tree, or Graph. Whether the compiler/interpreter allows you to access the class or not is in a different thing. Programing is about writing specifications that the computer can follow and other programers can read, List.Node is more explicit in that Node is internal to List than having ListNode as a first level class.
In some languages, the nested class will have access to variables that are in scope within the outer class. (Similarly with functions, or with class-in-function nesting. Of course, function-in-class nesting just creates a method, which behaves fairly unsurprisingly. ;) )
In more technical terms, we create a closure.
Python lets you do a lot of things with functions (including lambdas) that in C++03 or Java you need a class for (although Java has anonymous inner classes, so a nested class doesn't always look like your example). Listeners, visitors, that kind of thing. A list comprehension is loosely a kind of visitor:
Python:
(foo(x) if x.f == target else bar(x) for x in bazes)
C++:
struct FooBar {
Sommat operator()(const Baz &x) const {
return (x.f == val) ? foo(x) : bar(x);
}
FooBar(int val) : val(val) {}
int val;
};
vector<Sommat> v(bazes.size());
std::transform(bazes.begin(), bazes.end(), v.begin(), FooBar(target));
The question that C++ and Java programmers then ask themselves is, "this little class that I'm writing: should it appear in the same scope as the big class that needs to use it, or should I confine it within the scope of the only class that uses it?"[*]
Since you don't want to publish the thing, or allow anyone else to rely on it, often the answer in these cases is a nested class. In Java, private classes can serve, and in C++ you can restrict classes to a TU, in which case you may no longer care too much what namespace scope the name appears in, so nested classes aren't actually required. It's just a style thing, plus Java provides some syntactic sugar.
As someone else said, another case is iterators in C++. Python can support iteration without an iterator class, but if you're writing a data structure in C++ or Java then you have to put the blighters somewhere. To follow the standard library container interface you'll have a nested typedef for it whether the class is nested or not, so it's fairly natural to think, "nested class".
[*] They also ask themselves, "should I just write a for loop?", but let's suppose a case where the answer to that is no...
In C++ at least, one major common use-case for nested classes is iterators in containers. For example, a hypothetical implementation might look something like this:
class list
{
public:
class iterator
{
// implementation code
};
class const_iterator
{
// implementation code
};
};
Another reason for nested classes in C++ would be private implementation details like node classes for maps, linked lists, etc.
"Nested classes" can mean two different things, which can be split into three different categories by intent. The first one is purely stylistic, the other two are used for practical purposes, and are highly dependent on the features language where they are used.
Nested class definitions for the sake of creating a new namespace and/or organizing your code better. For example, in Java this is accomplished through the use static nested classes, and it is suggested by the official documentation as a way to create more readable and maintainable code, and to logically group classes together. The Zen of Python, however, suggests that you nest code blocks less, thus discouraging this practice.
import this
In Python you'd much more often see the classes grouped in modules.
Putting a class inside another class as part of its interface (or the interface of the instances). First, this interface can be used by the implementation to aid subclassing, for example imagine a nested class HTML.Node which you can override in a subclass of HTML to alter the class used to create new node instances. Second, this interface might be used by the class/instance users, though this is not that useful unless you are in the third case described below.
In Python at least, you don't need to nest the definitions to achieve either of those, however, and it's probably very rare. Instead, you might see Node defined outside of the class and then node_factory = Node in the class definition (or a method dedicated to creating the nodes).
Nesting the namespace of the objects, or creating different contexts for different groups of objects. In Java, non-static nested classes (called inner classes) are bound to an instance of the outer class. This is very useful because it lets you have instances of the inner class that live inside different outer namespaces.
For Python, consider the decimal module. You can create different contexts, and have things like different precisions defined for each context. Each Decimal object can assigned a context on creation. This achieves the same as an inner class would, through a different mechanism. If Python supported inner classes, and Context and Decimal were nested, you'd have context.Decimal('3') instead of Decimal('3', context=context).
You could easily create a metaclass in Python that lets you create nested classes that live inside of an instance, you can even make it produce proper bound and unbound class proxies that support isinstance correctly through the use of __subclasscheck__ and __instancecheck__. However, it won't gain you anything over the other simpler ways to achieve the same (like an additional argument to __init__). It would only limit what you can do with it, and I have found inner classes in Java very confusing every time I had to use them.
In Python, a more useful pattern is declaration of a class inside a function or method. Declaration of a class in the body of another class, as people have noted in other answers, is of little use - yes, it does avoid pollution of the module namespace, but since there_is_ a module namespace at all, a few more names on it do not bother. Even if the extra classes are not intended to be instantiated directly by users of the module, putting then on the module root make their documentation more easily accessible to others.
However, a class inside a function is a completely different creature: It is "declared" and created each time the code containing the class body is run. This gives one the possibility of creating dynamic classes for various uses - in a very simple way. For example, each class created this way is in a different closure, and can have access to different instances of the variables on the containing function.
def call_count(func):
class Counter(object):
def __init__(self):
self.counter = 0
def __repr__(self):
return str(func)
def __call__(self, *args, **kw):
self.counter += 1
return func(*args, **kw)
return Counter()
And using it on the console:
>>> #call_count
... def noop(): pass
...
>>> noop()
>>> noop()
>>> noop.counter
2
>>> noop
<function noop at 0x7fc251b0b578>
So, a simple call_counter decorator could use a static "Counter" class, defined outside the function, and receiving func as a parameter to its constructor - but if you want to tweak other behaviors, like in this example, making repr(func) return the function representation, not the class representation, it is easier to be made this way.
.

c++ namespace usage and naming rules

On the project we are trying to reach an agreement on the namespace usage.
We decided that the first level will be "productName" and the second is "moduleName".
productName::moduleName
Now if the module is kind of utility module there is no problem to add third namespace. For example to add "str": productName::utilityModuleName::str - to divide space where all "strings" related stuff will go.
If the module is the main business module we have many opportunities and almost no agreement.
For example
class productName::mainModuleName::DomainObject
and
class productName::mainModuleName::DomainObjectSomethingElseViewForExample
can be both at
namespace productName::mainModuleName::domainObject
class Data
class ViewForExample
Why should we create inner not private classes and not namespaces?
Why should we create class where all methods are static (except cases when this class is going to be template parameter)?
Project consist of 1Gb of source code.
So, what is the best practice to divide modules on namespaces in the c++?
What namespaces are for:
Namespaces are meant to establish context only so you don't have naming confilcts.
General rules:
Specifying too much context is not needed and will cause more inconvenience than it is worth.
So you want to use your best judgment, but still follow these 2 rules:
Don't be too general when using namespaces
Don't be too specific when using namespaces
I would not be so strict about how to use namespace names, and to simply use namespaces based on a related group of code.
Why namespaces that are too general are not helpful:
The problem with dividing the namespace starting with the product name, is that you will often have a component of code, or some base library that is common to multiple products.
You also will not be using Product2 namespaces inside Product1, so explicitly specifying it is pointless. If you were including Product2's files inside Product1, then is this naming conversion still useful?
Why namespaces that are too specific are not helpful:
When you have namespaces that are too specific, the line between these distinct namespaces start to blur. You start using the namespaces inside each other back and forth. At this time it's better to generalize the common code together under the same namespace.
Classes with all static vs templates:
"Why should we create inner not
private classes and not namespaces?
Why should we create classes where all
methods are static"
Some differences:
Namespaces can be implied by using the using keyword
Namespaces can be aliased, classes are types and can be typedef'ed
Namespaces can be added to; you can add functionality to it at any time and add to it directly
Classes cannot be added to without making a new derived class
Namespaces can have forward declarations
With classes you can have private members and protected members
Classes can be used with templates
Exactly how to divide:
"Project consist of 1Gb of source
code. So, what is the best practice to
divide modules on namespaces in the
c++?"
It's too subjective to say exactly how to divide your code without the exact source code. Dividing based on the modules though sounds logical, just not the whole product.
This is all subjective, but I would hesitate to go more than 3 levels deep. It just gets too unwieldy at some point. So unless your code base is very, very large, I would keep it pretty shallow.
We divide our code into subsystems, and have a namespace for each subsystem. Utility things would go into their own namespace if indeed they are reusable across subsystems.
It seems to me that you are trying to use namespaces as a design tool. They are not intended for that, they are intended to prevent name clashes. If you don't have the clashes, you don't need the namespaces.
I divide namespaces depending on its usages:
I have a separate namespace, where I have defined all my interfaces (pure virtual classes).
I have a separate namespace, where I have defined my library classes (like db library, processing library).
And I have a separate namespace, where I have my core business (business logic) objects (like purchase_order, etc).
I guess, its about defining it in a way, that doesn't becomes difficult to handle in the future. So, you can check the difficulties that will surround on your current design.
And if you think they are fine, you should go with it.