At my OOP theory exam I was asked a question "What is a metaclass? What is a metaclass of metaclass?". I answered first one easily, but have no idea about the second one. Is there even something like "metaclasses of metaclasses" in any programming language, or even theoritically? I tried implementing something like that in Python 3, but it seems it's a bit too complicated for my (I only had simple Python course for 1 semester).
Yes.
I will use the Python language to explain how can that be - maybe it is the language where metaclasses are more palpable (at least it is the language with the majority of questions involving metaclasses here).
So, in an OOP language where "classes" are first class objects - that is, they are themselves objects, and all the rules that apply to other objects apply to classes as well - they just happen to be the "template" for other kind of objects, these classes themselves are instances of "something". This something is the "metaclass" - which is just a word to designate the "class of a class".
And it happens that this "metaclass", the class of a class is an object as well, just as other classes. And as such, it also is an instance of a class - this class of the metaclass is what can be named the "metametaclass".
Now, bringing it down to a concrete example in Python - by default, the metaclass for classes in Python is type. That is, type is the class which instances are classes.
The language does have ingenious mechanisms that make it practical in some points to inherit a class from type, and then work with custom meta-classes.
So, what is the class of type? That will be the "metametaclass" for most (or all) classes in Python.
And as it goes, the class of "type" is "type" itself. yes - it is a circular reference, without which the object hierarchy of the language could not be bootstraped. I don't know if other languages do that differently - but in Python it is quite patent:
>>> class A:
... pass
...
>>> type(A)
<class 'type'>
>>> type(type(A))
<class 'type'>
>>> type(type(A)) is type(A)
True
Now, besides working like that as a concept, it actually can be used as a metametaclass, and there are mechanisms of the language that can be tweaked by inheriting type for that purpose. (Normally it will be inherited to be customized as an "ordinary" metaclass).
By coincidence, I had an use case for the "metametaclass" exemplified this very week, in a question here - by customizing Python's type __call__ method, instead of __new__ or __init__, and using this custom class as the "metaclass for a metaclass" one can actually control how those methods are called and the parameters passed to them methods when an ordinary class is be created.
Related
Essentially, what is the difference in defining class using baseclass "object", vs without any baseclass. I have seen classes are defined with baseclass "object" many times.
class MyClass(object):
def __init__(self. *params):
self.params = params
Or,
class MyClass:
def __init__(self. *params):
self.params = params
In Python 3.x, which is the de facto Python language nowadays, there are no differences at all: either have an explicit inheritance from object, or leaving the bases blank is absolutely the same thing.
For Python 2, however it is another matter -
After the language evolved Object Oriented sintaxes with what today are called "classic classes", a series of better features in the inheritance mechanisms, memory allocation, object initialization, attribute retrieval was thought of, and then object was introduced, back in Python 2.2 as the base for what was called "new style classes" in Python 2.x life cycle.
So, if you see some code that is supposed to run in Python 2, not inheriting from object, is almost always an error - which can cause hard to find incorrect behaviors to take place at run time (for example type(instance) will not work properly, you can't use descriptors, such as "properties" and so on).
As stated above, however, all classes in Python 3.0 and above are "new style classes". Explicitly inheriting from object is interesting when one would write code that should run correctly both in Python 2 and Python 3 - few projects today focus on keeping Python 2 compatibility, and that is why one will see less and less "object" as an explicit base in new code.
I feel like this subject is touched in some other questions but it doesn't get into Python (3.7) specifically, which is the language I'm most familiar with.
I'm starting to get the hang of abstract classes and how to use them as blueprints for subclasses I'm creating.
What I don't understand though, is the purpose of concrete methods in abstract classes.
If I'm never going to instantiate my parent abstract class, why would a concrete method be needed at all, shouldn't I just stick with abstract methods to guide the creation of my subclasses and explicit the expected behavior?
Thanks.
This question is not Python specific, but general object oriented.
There may be cases in which all your sub-classes need a certain method with a common behavior. It would be tedious to implement the same method in all your sub-classes. If you instead implement the method in the parent class, all your sub-classes inherit this method automatically. Even callers may call the method on your sub-class, although it is implemented in the parent class. This is one of the basic mechanics of class inheritance.
I am a self-taught python user (kind of.). I read much to deepen my knowledge about python. Today
I encountered a text saying:
... classes and objects ....
So I was wondering what is the difference between objects and classes in python. I taught all classes are objects, but in that case, author wouldn't have used phrase "classes and objects". I'm confused...
These are two closely related terms in object oriented programming. The standard meaning is that an object is an instance of a class.
An object is an instantiation of a class.
Think of a class like the blueprint of a car.
Ford make cars (objects) based on the rules and information enclosed in the blueprint.
Yes, classes (and functions, and modules, and basically everything) in Python are objects, too. The difference lies in their types:
class Foo(object): pass
print type(Foo)
print type(Foo())
To see they're both objects, you can check that they both have attributes:
print dir(Foo)
print dir(Foo())
A class describes what that object will be, but it isn't the object itself.
A class is an idea. An object is the fruition of that idea.
I am learning about virtual function tables and their representation by analyzing a binary of a simple program written in Visual C++ (with some optimizations on).
A few days ago I asked this question while being stuck on virtual method table content with identical COMDAT folding on.
Now I'm stuck on something else: whenever I analyze a class, I need to find its Virtual Method Table. I can do this by finding either its RTTITypeDescriptor or _s_RTTIClassHierarchyDescriptor, finding a cross reference on it, which should lead me to the _RTTICompleteObjectLocator. When I find a cross reference to the Complete Object Locator, it is written just before the VMT (basically -1st entry of the VMT).
This approach works on some classes (their names start with C in my program). Then there are classes, that are named with I in the beginning and I am able to pair them with other classes starting with C -- for example there is class CClass and it inherits from IClass. These I-classes are probably serving as interfaces to the C-classes and thus they probably only contain abstract methods.
By searching a cross reference to Type Descriptor or Class Hierarchy Descriptor of any of the I-classes I cannot find anything -- there is no Complete Object Locator that would lead me to the VMT of the class (that should be full of references to pure_virtual call if I am correct about the all-abstract methods in the I-classes and if I understand correctly what VMT of abstract class looks like).
Why do the I-classes have no VMT? Did the compiler optimize it out because it would just be full of references to pure_virtual call and manages it in a different way?
These "interfaces" abstract classes probably have need no user written code in any their constructors and destructors (these either have an empty body and no ctor-init-list, or simply are never user defined); let's call these pure interface classes.
[Pure interface class: concept related but not identical to Java interfaces that are (were?) defined as having zero implementation code, in any member function. But be careful with analogies, as Java interfaces inheritance semantic isn't the same as C++ abstract classes inheritance semantic.]
It means that in practice no used object ever has pure interface class type: no expression ever refers to an object with pure interface type. Hence, no vtable is ever needed, so the vtable, which may have been generated during compilation, isn't included in linked code (the linker can see the symbol of the pure interface class vtable isn't used).
I came across the following description of IsRoot, IsAbstract & IsLeaf however do not understand when you would used them.
Excerpt from http://www2.sys-con.com/itsg/virtualcd/dotnet/archives/0108/clark/index.htm:
By checking the IsRoot check box, you are restricting the class from inheriting from other classes. Checking IsAbstract restricts the class from being instantiated, and forces clients to instantiate a derived class to access the functionality of the class. Checking IsLeaf indicates that the class is sealed. Sealed classes are noninheritable and help to limit the depth of an inheritance chain.
My understanding
IsRoot seems to suggest that it is a superclass
IsAbstract seems to suggest it is an abstract class
IsLeaf is a class that cannot be inherited but can be instantiated.
Can someone give me a real-world example of a model that uses these? For example I can imagine class such as 'car' that is a superclass and is abstract and beneath it you would have classes such as 'Volvo', 'Chevrolet', etc.
isRoot no longer exists in UML2. In UML 1 it means (from the specification) :
isRoot: Specifies whether the GeneralizableElement is a root
GeneralizableElement with no ancestors. True indicates that it
may not have ancestors, false indicates that it may have ancestors
(whether or not it actually has any ancestors at the moment).
isAbstract means that the element is incomplete and cannot be instantiated.
If true, the Classifier does not provide a complete declaration and can typically not be instantiated. An abstract
classifier is intended to be used by other classifiers (e.g., as the target of general metarelationships or generalization
relationships). Default value is false.
isLeaf means that you cannot redefine the element, same as final in some programming languages.
Indicates whether it is possible to further redefine a RedefinableElement. If the value is true, then it is not possible to
further redefine the RedefinableElement. Default
value is false.
Not real-life examples, but links to some.
isRoot: I think this is no longer part of UML. That article is from 2004, which was around the time UML 2 came out, and I doubt Visio supported it. It still may not support it.
isAbstract: it's a good idea to make all superclasses abstract so that you cannot create an instance that is not a member of the subclasses. Classes are essentially sets of instances. What does it mean for an instance to be a member of a superset and none of the subsets? It's unclear exactly what the classification of such an instance is, and it may inadvertently change over time. It's also a good idea to make the subclasses disjoint (non-overlapping) and covering (all known subclasses specified). There's more details and a real-life example of this using Avians in Lahman's book.
isLeaf: essentially keeps people from overriding your code. I can't verify this quotation, but supposedly the The Unified Modeling Language Reference Manual says:
Being a leaf or being constrained to be a leaf are not fundamental
semantic properties but rather software engineering mechanisms to
control human behavior.
Does that help?