ADT is the set of operations. ADT's are mathematical abstractions.
Does this mean that ADT are same as classes or am i confusing both together ?
The key to the difference is abstract. Think of an ADT more like an interface - a class with only method declarations, no implementation details.
As an example, a Stack ADT defines the basic stack operations like push and pop (but says nothing of how these operations should be implemented), while a Stack class would use either a linked-list or an array to actually implement these operations.
According to Code Complete, ADT is a collection of data and operations that work on that data.
Example for ADT:
List
Initialize list
Insert item in list
Remove item from list
Read next item from list
ADT form the foundation for the concept of classes. In languages that support classes, you can implement each abstract data type as its own class. Classes usually involve the additional concepts of inheritance and polymorphism. One way of thinking of a class is as an abstract data type plus inheritance and polymorphism.
An abstract data type (ADT) is a mathematical abstraction of a real world thing and can be implemented in a concrete data type in different languages.
An ADT defines operations for the given type and mathematically expresses their behaviour.
Concrete implementations of an ADT can differ from each other. In that way classes are implementing the ADT and methods implement operations.
Classes have a slightly different terminology than ADTs and add other characteristics, like:
they for example may live in packages
their members are called attributes and methods
attributes and methods have a certain visibility constraint
And methods:
can be abstract, too. but then, their behaviour isn't defined - only their method signature - an inheriting concrete class must provide an implementation
Don't confuse abstract data types with abstract classes in a concrete language.
A class is an implementation of an abstract data type (ADT).
ADTs are the way of classifying data structure by providing a minimal expected interface and set of Method
ADT's = set of values + Operation
Example Stack, Queue
Related
I am reading Autosar document and in one of the document (Autosar_TemplateModelingGuideline.pdf), it says that:
Composite aggregation, forming a whole-part relationship
Regular association, expressing a reference from the associating to
the associated model element
My question is: what is the difference between these two in practice? How do I have to interpret them in a class diagram, e.g. the Com Module in Autosar.:
The AUTOSAR COM module’s Configuration Overview
Consider Specified class ComGwSignalRef surrounded with a red rectangle. This class has a composition relation with ComGwSignalRef class and two regular association with ComGroupSignal and ComSignal.
How would you interpret this as a developer and how do you implement in C?
if regular association is a reference to an object that has independent life from ComGwSignalRef why designer do not use instanceRef here?
if it is not a reference, why did the designer not use composition?
PS. There is a concept in Autosar "InstanceRef" which is used for reference for independent object with independent lifecycle.
Maybe you should also consider the following:
The Com Configuration is an instance of the EcuC configuration meta-model as defined in the AUTOSAR_TPS_EcuConfiguration.
The ComGwSignalRef is of type EcucChoiceContainerDef, and as such, the two destination associations of ComSignal and ComGroupSignal have a meaning. Only one of these "choices" can be selected in the final configuration as a reference. In AUTOSAR metamodel, that is the definition of how EcucChoiceContainerDef works, in UML you might need here an additional constraint element to define the XOR relation of two associations.
An object can only be composed as part of one object.
A <>- C -<>B
In the diagram above C is composed in A and B. This would lead to the following instances:
a: A <>- c: C -<> b:B
Now the specific instance c is now part of both a and b.
What happen would with c if b goes out of scope? By the semantics it should be destroyed and not be destroyed (a still exists).
Or more pointed:
Take Alice,Bob, and Collar Bone as examples. Alice’s collar bone cannot be part of Bob.
UML is a modeling language and has not the same expressiveness as, say a C compiler. This is by design to simplify things.
Remember: All models are wrong, but some are useful. — George E. P. Box
I have read multiple times the answers in this question about the TArray<T> and the array of T. From what I have understood the use of the first is more versatile than the latter because for a dynamic array I should declare a type like...
type
TMyFlexibleArray = array of Integer;
... that is needed (in certain cases) because I cannot return an array of Integer for example. Instead, of course, I can return a generic type. Dynamic arrays don't have a fixed length and memory for them is reallocated with the SetLength procedure. TArray is a generic class with static methods; the documentation about it states:
You should not create instances of this class, because its only
purpose is to provide sort and search static methods.
They have two different natures/functions but do they have the same result (for example when passed as parameter or when I just need a flexible container)? I see that TArray has also some useful method.
Is is correct if I say that TArray<T> is a dynamic array built with generics and type K = array of T is an own dynamic array (a custom one)? In my question I assume that they are equivalent in their function of being dynamic arrays (and I prefer the generic way just for comfort).
Generic dynamic arrays and non generic dynamic arrays are identical in every way, apart from their generic, or otherwise, nature. That is the single difference.
That difference drives decision making in the few scenarios where one can be used but not the other. For instance:
For reasons outlined in your question, generic arrays are sometimes necessary when working with generic types.
On the other hand, when writing code that you wish to compile on old compilers that pre-date generics, then you cannot use generic arrays.
If this seems obvious, that's because it is. There really is just this one single difference between generic and non-generic arrays.
You also mention the class TArray from System.Generics.Collections. That's a static class containing methods to search and sort arrays. It's completely different from any dynamic array types and something of a distraction here. Although the names are similar, TArray<T> and TArray these are quite different things. Ignore TArray for the purpose of this question.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I need to design, for a school project, a very simple GUI framework which needs to support the following controls/widgets: Window, Panel, Image, Label and Button.
The first question that came up to my mind is whether or not Window should be a control. I think it suppose to.
We have Window and Panel which can contain other controls. Button, Label and Image, cannot. So we need two basic types of controls; One which is a container and another which is not (I've seen that in Gtk implementation the later is also a container, but can only contain one single child. It's called GtkBin. I think it's an overhead for my simple project.
Third issue I came across with is: I need to traverse the UI tree (for the drawing) but since there's no mechanism for polymorphism in C, it's becoming somewhat problematic.
I thought about the following solution, utilizing union. Basically I'll need some function to convert a generic Control to it's actuall type.
typedef struct button {
char *image_path;
} Button;
typedef struct control_node {
Control *node;
struct control_node *next;
} ControlNode;
typedef struct panel {
ControlNode *children;
} Panel;
typedef union control_data {
Panel panel;
Button button;
} ControlData;
typedef struct control {
int x;
int y;
int type;
ControlData *data;
} Control;
So I'd like to get your thoughts about the issues I've introduced and an opinion about my current strategy (I am NOT looking for an implementation, rather thoughts/ideas etc)
Thanks.
You should put a void * first thing in the layout of every "GUI class" that will point to manually implemented v-tables for every type. The first function in every type's v-table could be one, returning a unique integer for every type (or just be a unique integer), so you can tell what is what and have some type safety implemented. Although it is not necessary, you could use the v-table pointer value to determine the type (since it will be unique), which will save on memory, but will be a little less obvious. It is also crucial to have virtualism in the object destruction, so a destructor function for handling each unique type's internals with its position in the v-table being consistent is also a must. Although for your task this might actually be avoidable, but for production it is a must.
As for the actual tree, this should be built on a simple parent-child relation, revolving around a leaf and node interface, the leaf only holding a pointer to the parent, the node also including a dynamic list type you must also implement. Then traversing the tree is fairly straightforward.
You can modularize a bit by using "interfaces" structs and aggregation in lieu of inheritance, but it won't save you much effort compared to implementing every type on its own, as long as you keep the v-table pointer the first object in the type layout, so that you know what you are working with and how to use it. The layout of the rest is not that crucial to follow any guidelines, as long as you know the type and cast the pointer to the appropriate struct type. But since every object will have a parent, even the root, which will be identifiable by its parent being 0, you really should put the parent second after the v-table pointer, this way you can avoid casting when all you need to access is the parent.
Another thing you can benefit from is using signals, as in have another pointer in every button, so you can assign it to a function to be executed when you "click" the button.
There are 2 different problems here: the conception of the GUI and its implementation in C. If conception is simpler in OO model, just write it that way. As first C++ compiler were just preprocessors for C code, C can implement OO modeling with the use of vtables.
First define clearly what are your objects (classes): which can be containers, which are drawables, which can react to mouse or keyboard events. What are their properties: text, x-y coordinates, bitmaps, and probably a z-coordinate. At the end of that phase, you should have a hierachy of classes with properties and methods, and possible overrides in subclasses - if you have learned it, UML could help for that part.
Second, you will have to implement that in C. Don't worry about it. You will not have the syntactic sugar of copy and move constructors for free, nor the notion of public, private and protected attributes, but struct can contain sub-objects, pointers to other structs and pointer to functions.
You just need a lexicon to translate OO tools in C :
class: struct
field of class: field of struct
method of class: function whose first attribute is a pointer to an instance of the struct
virtual method : pointer to a method
constructor and destructor : special methods that must be called explicitely - no automatic destruction if a struct goes out of scope
A non final class (contains virtual methods) should contain a VTABLE, which is a mere array of pointers to the virtual methods. This VTABLE should be first element of struct to ease class pointer casting. A derived class first contains its own vtable (if it is not final), then its attributes and then an instance of its parent. A cast from parent to derived pointer is just a matter of adding an offset. If you need multiple inheritance, you add the other parents after the first in the struct. Virtual inheritance would be slightly tougher to implement because it involves pointers in the VTABLE. Same if you need class aware objects, just add a constant in the VTABLE. But I do not think that you need all that for your requirement.
So look twice if you really want the harder bits: multiple inheritance and class aware objects, then just implement each class in its .h + .c file. You even get for free private methods: they are just static functions.
I'm looking for a GObject cheat sheet, how common OOP concepts map to GObject's facilities. Consider for example:
AnyGObject *o;
o = anygobject_new();
Now, what are the conventions for...
calling a method
calling a method declared by a base class
calling a method declared by an interface the class is implementing
calling a class method
calling a class method declared by a base class
calling a virtual method
casting to a base class
casting to a derived class
casting to an interface the class is implementing
testing whether an object is of a particular type
...
Clarification:
The GObject Reference Manual and GObject HowTo explain at length how to create a new class (class struct, object struct, private struct, various macros, conventions). Taken together these facilities allow for OOP. Yet there seems to be no tutorial on how to use them consistently.
This answer assumes you are working with C. Other (usually object-oriented) languages have special bindings built to make working with GObject seem more natural.
If you've worked with GTK+, you already have done much of that list.
GObject methods are not members themselves (there is a vtable of sorts but it's only used for assigning virtual method implementations in a derived class when the class is first created). Instead, all methods in GObject are just plain functions, usually(?) prefixed by a method name prefix, and with the this pointer as the first argument.
For example, the C++ method
namespace Lib { // short for Library; to demonstrate GObject's idiomatic naming conventions
class Foo {
public:
void Bar(int z);
};
}
would be a plain function in the global namespace declared as
void lib_foo_bar(LibFoo *foo, int z);
and you would call it directly, just like any other C function.
Class derivation in GObject occurs by having the full data structure of the parent class as the first member of the derived class's data structure. For various reasons pertaining to rarely-discussed clauses in the C standard (and possibly the System V ABI and implementation of gcc, clang, and even the Microsoft C compilers), this means that a pointer to an object of the derived class is equivalent to a pointer to the parent class!
So if LibBaz derives from LibFoo, all you would need to say is
LibFoo *foobaz = (LibFoo *) baz;
and the same applies in reverse:
LibBaz *bazfoo = (LibBaz *) foo;
(This latter approach is what GTK+ uses for GtkWidget; I don't know if other GObject libraries do the same thing.)
Idiomatic GObject declarations include a bunch of macros that make the type conversions more terse while at the same time adding runtime type safety checks. Our LibFoo class would have the following macros:
#define LIB_TYPE_FOO (lib_foo_get_type())
#define LIB_FOO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LIB_TYPE_FOO, LibFoo))
With this, we would instead say
LibFoo *foobaz = LIB_FOO(baz);
LibBaz *bazfoo = LIB_BAZ(foo);
and if either baz or foo isn't the correct type for the conversion, a warning will be logged to standard error, which you can break at and investigate using a debugger.
(The lib_foo_get_type() function (and LIB_TYPE_FOO neatness macro) is important: it returns a numeric ID that maps to the type of LibFoo for future reference. If LibFoo doesn't have such a mapping, it will create the mapping, registering the type and creating the virtual method mappings.)
A similar macro allows type checking:
#define LIB_IS_FOO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LIB_TYPE_FOO))
which is a simple expression that can be used in an if statement.
So what about calling parent class methods? Well, if we put all of the above together, we have the answer:
lib_foo_parent_method(LIB_FOO(aLibBazInstance), params);
The same applies to virtual methods. Virtual methods are implemented using the GObject approximation to vtables and are transparent to the end programmer. All you will do is
lib_foo_virtual_method(LIB_FOO(whatever), params);
(If you actually build the derived class itself, the how of virtual methods becomes important.)
There are no static methods in GObject, because methods aren't tied to a class as closely as they are in real object-oriented languages. Just create a top-level method in your library:
void lib_something_common(params);
Finally, all of the above applies to interfaces. Interfaces work the exact same way to the end user; they use the same
void lib_iface_method(LibIface *iface, params);
approach to method calling, the same casting rules, and the same LIB_IFACE() and LIB_IS_IFACE() helper macros.
Hopefully that helps! Any further explanation would have to tread into explaining how to create a GObject, which I tried to keep outside the scope of this answer for simplicity's sake, but is a useful thing to know anyway.
What distinguishes and object from a struct?
When and why do we use an object as opposed to a struct?
How does an array differ from both, and when and why would we use an array as opposed to an object or a struct?
I would like to get an idea of what each is intended for.
Obviously you can blur the distinctions according to your programming style, but generally a struct is a structured piece of data. An object is a sovereign entity that can perform some sort of task. In most systems, objects have some state and as a result have some structured data behind them. However, one of the primary functions of a well-designed class is data hiding — exactly how a class achieves whatever it does is opaque and irrelevant.
Since classes can be used to represent classic data structures such as arrays, hash maps, trees, etc, you often see them as the individual things within a block of structured data.
An array is a block of unstructured data. In many programming languages, every separate thing in an array must be of the same basic type (such as every one being an integer number, every one being a string, or similar) but that isn't true in many other languages.
As guidelines:
use an array as a place to put a large group of things with no other inherent structure or hierarchy, such as "all receipts from January" or "everything I bought in Denmark"
use structured data to compound several discrete bits of data into a single block, such as you might want to combine an x position and a y position to describe a point
use an object where there's a particular actor or thing that thinks or acts for itself
The implicit purpose of an object is therefore directly to associate tasks with the data on which they can operate and to bundle that all together so that no other part of the system can interfere. Obeying proper object-oriented design principles may require discipline at first but will ultimately massively improve your code structure and hence your ability to tackle larger projects and to work with others.
Generally speaking, objects bring the full object oriented functionality (methods, data, virtual functions, inheritance, etc, etc) whereas structs are just organized memory. Structs may or may not have support for methods / functions, but they generally won't support inheritance and other full OOP features.
Note that I said generally speaking ... individual languages are free to overload terminology however they want to.
Arrays have nothing to do with OO. Indeed, pretty much every language around support arrays. Arrays are just blocks of memory, generally containing a series of similar items, usually indexable somehow.
What distinguishes and object from a struct?
There is no notion of "struct" in OOP. The definition of structures depends on the language used. For example in C++ classes and structs are the same, but class members are private by defaults while struct members are public to maintain compatibility with C structs. In C# on the other hand, struct is used to create value types while class is for reference types. C has structs and is not object oriented.
When and why do we use an object as opposed to a struct?
Again this depends on the language used. Normally structures are used to represent PODs (Plain Old Data), meaning that they don't specify behavior that acts on the data and are mainly used to represent records and not objects. This is just a convention and is not enforced in C++.
How does an array differ from both,
and when and why would we use an
array as opposed to an object or a
struct?
An array is very different. An array is normally a homogeneous collection of elements indexed by an integer. A struct is a heterogeneous collection where elements are accessed by name. You'd use an array to represent a collection of objects of the same type (an array of colors for example) while you'd use a struct to represent a record containing data for a certain object (a single color which has red, green, and blue elements)
Short answer: Structs are value types. Classes(Objects) are reference types.
By their nature, an object has methods, a struct doesn't.
(nothing stops you from having an object without methods, jus as nothing stops you from, say, storing an integer in a float-typed variable)
When and why do we use an object as opposed to a struct?
This is a key question. I am using structs and procedural code modules to provide most of the benefits of OOP. Structs provide most of the data storage capability of objects (other than read only properties). Procedural modules provide code completion similar to that provided by objects. I can enter module.function in the IDE instead of object.method. The resulting code looks the same. Most of my functions now return stucts rather than single values. The effect on my code has been dramatic, with code readability going up and the number of lines being greatly reduced. I do not know why procedural programming that makes extensive use of structs is not more common. Why not just use OOP? Some of the languages that I use are only procedural (PureBasic) and the use of structs allows some of the benefits of OOP to be experienced. Others languages allow a choice of procedural or OOP (VBA and Python). I currently find it easier to use procedural programming and in my discipline (ecology) I find it very hard to define objects. When I can't figure out how to group data and functions together into objects in a philosophically coherent collection then I don't have a basis for creating classes/objects. With structs and functions, there is no need for defining a hierarchy of classes. I am free to shuffle functions between modules which helps me to improve the organisation of my code as I go. Perhaps this is a precursor to going OO.
Code written with structs has higher performance than OOP based code. OOP code has encapsulation, inheritance and polymorphism, however I think that struct/function based procedural code often shares these characteristics. A function returns a value only to its caller and only within scope, thereby achieving encapsulation. Likewise a function can be polymorphic. For example, I can write a function that calculates the time difference between two places with two internal algorithms, one that considers the international date line and one that does not. Inheritance usually refers to methods inheriting from a base class. There is inheritance of sorts with functions that call other functions and use structs for data transfer. A simple example is passing up an error message through a stack of nested functions. As the error message is passed up, it can be added to by the calling functions. The result is a stack trace with a very descriptive error message. In this case a message inherited through several levels. I don't know how to describe this bottom up inheritance, (event driven programming?) but it is a feature of using functions that return structs that is absent from procedural programming using simple return values. At this point in time I have not encountered any situations where OOP would be more productive than functions and structs. The surprising thing for me is that very little of the code available on the internet is written this way. It makes me wonder if there is any reason for this?
Arrays are ordered collection of items that (usually) are of the same types. Items can be accessed by index. Classic arrays allow integer indices only, however modern languages often provide so called associative arrays (dictionaries, hashes etc.) that allow use e.g. strings as indices.
Structure is a collection of named values (fields) which may be of 'different types' (e.g. field a stores integer values, field b - string values etc.). They (a) group together logically connected values and (b) simplify code change by hiding details (e.g. changing structure layout don't affect signature of function working with this structure). The latter is called 'encapsulation'.
Theroretically, object is an instance of structure that demonstrates some behavior in response to messages being sent (i.e., in most languages, having some methods). Thus, the very usefullness of object is in this behavior, not its fields.
Different objects can demonstrate different behavior in response to the same messages (the same methods being called), which is called 'polymorphism'.
In many (but not all) languages objects belong to some classes and classes can form hierarchies (which is called 'inheritance').
Since object methods can work with its fields directly, fields can be hidden from access by any code except for this methods (e.g. by marking them as private). Thus encapsulation level for objects can be higher than for structs.
Note that different languages add different semantics to this terms.
E.g.:
in CLR languages (C#, VB.NET etc) structs are allocated on stack/in registers and objects are created in heap.
in C++ structs have all fields public by default, and objects (instances of classes) have all fields private.
in some dynamic languages objects are just associative arrays which store values and methods.
I also think it's worth mentioning that the concept of a struct is very similar to an "object" in Javascript, which is defined very differently than objects in other languages. They are both referenced like "foo.bar" and the data is structured similarly.
As I see it an object at the basic level is a number of variables and a number of methods that manipulate those variables, while a struct on the other hand is only a number of variables.
I use an object when you want to include methods, I use a struct when I just want a collection of variables to pass around.
An array and a struct is kind of similar in principle, they're both a number of variables. Howoever it's more readable to write myStruct.myVar than myArray[4]. You could use an enum to specify the array indexes to get myArray[indexOfMyVar] and basically get the same functionality as a struct.
Of course you can use constants or something else instead of variables, I'm just trying to show the basic principles.
This answer may need the attention of a more experienced programmer but one of the differences between structs and objects is that structs have no capability for reflection whereas objects may. Reflection is the ability of an object to report the properties and methods that it has. This is how 'object explorer' can find and list new methods and properties created in user defined classes. In other words, reflection can be used to work out the interface of an object. With a structure, there is no way that I know of to iterate through the elements of the structure to find out what they are called, what type they are and what their values are.
If one is using structs as a replacement for objects, then one can use functions to provide the equivalent of methods. At least in my code, structs are often used for returning data from user defined functions in modules which contain the business logic. Structs and functions are as easy to use as objects but functions lack support for XML comments. This means that I constantly have to look at the comment block at the top of the function to see just what the function does. Often I have to read the function source code to see how edge cases are handled. When functions call other functions, I often have to chase something several levels deep and it becomes hard to figure things out. This leads to another benefit of OOP vs structs and functions. OOP has XML comments which show up as tool tips in the IDE (in most but not all OOP languages) and in OOP there are also defined interfaces and often an object diagram (if you choose to make them). It is becoming clear to me that the defining advantage of OOP is the capability of documenting the what code does what and how it relates to other code - the interface.