Apr
14

Reusing Code by Inheritance

by Tomi Maila, Apr 14, 2007 at 8:45 pm
1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.75 out of 5)
Loading ... Loading ...

In our last topic in article series Introduction to Object-Oriented Programming in LabVIEW I explained how real world objects form conceptual hierarchies. This concept of hierarchies is also present in object-oriented programming where building block can have hierarchical relationships. This concept of hierarchical relationships of software modules in object-oriented programming is called inheritance, as explained last time.

Inheritance in practice

So what does inheritance practically mean in the context of object-oriented programming? Why would we like to define class hierarchies?

Let’s first define some concepts. When a class inherits from another class we call the class upper in the hierarchy a parent class and the class lower in the hierarchy a child class. Further we call parent, parent’s parent and all other classes up in the inheritance chain ancestor classes. Likewise we call all classes down the inheritance chain descendant classes. In the picture below these concepts are visualized for the class Car.

Terminology in LabVIEW object-oriented programming

As we explained earlier a class in object-oriented programming is a user defined datatype that encapsulates both data and functionality. In comparison conventional LabVIEW data types only carry data. As classes are types in object-oriented programming, wires of class types are called objects.

Each class in object-oriented programming specifies some functionality. To implement this functionality the class developer writes a set of method VIs. The method VIs are an integral part of the class. In addition the class developer specifies some internal or private data type for the class. This data type is a cluster. Note that the unlike conventional clusters, this cluster can also be empty.

Reusing ancestor methods

So what’s all the fuss about inheritance? Inheritance allows a developer of the descendant class to reuse much of the code in any of the ancestor classes. If an ancestor class has a method public method VI, this method is available also in any of the descendant classes. Furthermore if objects of ancestor class carry data of certain type, then all the descendent classes carry similar data of the same type.

Let’s take an example. Consider a land vehicle class. As each land vehicle has wheels, we decide to specify that a land vehicle class cluster of private data is an array of wheels. Cluster of private data is a place where the developer specifies the data type that is carried by the wire. Now our all objects of Land Vehicle class as well as all objects of any of the descendant classes of Land Vehicle would carry array of wheels as private data. In addition descendant of Land Vehicle can carry other private data as well but they would always carry at least an array of Wheels.

We cannot fix the number of wheels as some vehicles such as bicycle has only few wheels and others such as a train have more wheels. Further we cannot add an engine to cluster of private data as not all land vehicles have engines. The picture below illustrates the private data of our Land Vehicle class.

Private data of Land Vehicle class

Now we define a public method VI Add Wheel.vi to Land Vehicle class. This method would add a wheel to a vehicle. Now each descendant class of class Land Vehicle would also have these two methods automatically. Land Vehicle would be a kind of a template or a starting point from which we can now build different kinds of land vehicles such as a car or a bicycle.

VI interface of Add Wheel.vi


Class Land Vehicle is a parent class of classes Car, Bicycle and Motorcycle. Now comes the interesting part. All these three classes can call the Add Wheel.vi method as if it was their own. The picture below illustrates this ability.

Add Wheel

So by inheriting classes Car, Bicycle and Motorcycle form a common parent class Land Vehicle, we can share code related to adding wheels to different kind of vehicles between these three classes. The same generality cannot be achieved in classic dataflow programming with such an elegant way.

Passing descendant classes as arguments

Consider you want to travel from Paris to Berlin. Unless you want to walk, you would need a vehicle to take you to Berlin. However it could be an aircraft, a land vehicle or even a watercraft. So generally you could say that any vehicle could be used to travel from Paris to Berlin.

Similar way thinking can be applied to object-oriented programming. When any VI expects an input of general class type then any of its descendants can be passed as an argument as well. So should you have a VI Travel by Land.vi that expects an object of class Land Vehicle as an input, you can pass any object of any descendant class of class Land Vehicle as an argument. This is illustrated by the following picture. The VI expects a Land Vehicle (right) and we pass a Car which is a child of Land Vehicle (left).

Travel by Land

In the previous example we showed how we can reuse ancestor method VIs in descendant classes. However this is not the only benefit of inheritance and class hierarchies. In addition to reusing ancestor class code, we can also pass descendent classes as arguments where ancestor class is expected. Alternatively we can create an array of different kinds of Land Vehicles as select one of the items in an array using index array.

Travel by Land with array of objects

Conclusions

In LabVIEW object-oriented programming or LabVOOP for short we developers can share parent or other ancestor class code between all the decedents of that class. This is a great benefit when software components with shared properties are needed. In my next article in this series I’ll talk about class interfaces, how the interfaces can be shared between classes in the hierarchy and how this greatly enhances software development process. Subscribe to the RSS feed of this blog not miss it.

Print This Post Print This Post

Apr
02

Inheritance and Class Hierarchies in Object-Oriented Programming

by Tomi Maila, Apr 2, 2007 at 12:56 pm
1 Star2 Stars3 Stars4 Stars5 Stars (10 votes, average: 4.50 out of 5)
Loading ... Loading ...

As the third topic in my article series Introduction to Object-Oriented Programming in LabVIEW I’ll talk about inheritance and conceptual hierarchies in object oriented programming.

Hierarchies of real-world objects

Object of the real world often form conceptual hierarchies. For example a bicycle, a motorcycle and a car are all examples of different kinds of vehicles. A bus, a truck and an SUV are examples of different kinds of cars. These relationships between similar objects can be visualized using diagrams similar to one below.

Hierarchy of Vehicles

 

All vehicles share common properties and common functionality. For example all vehicles have one or more wheels and they are designed for transportation purposes. We can also fairly safely say that all vehicles have some sort of steering method.

All cars share even more common properties and common functionality. A steering wheel is used for steering the cars. An engine is used as a power source. All cars have at least four wheels and the wheels are symmetrically distributed on both sides of the car.

We can say that the word vehicle defines a class of real-world objects for transportation and so does the words car, bicycle and motorcycle. As cars, bicycles and motorcycles are all special kinds of vehicles as well we can say that words car, bicycle and motorcycle all define subclasses of class vehicle. In a similar way bus, truck and SUV can all be considered subclasses of class car as they are special kinds of cars.

Class hierarchies in object-oriented programming

It’s often the case that the building blocks of a software project form similar conceptual relationship hierarchies. Consider for example the following build-in LabVIEW types.

Numeric Types in LabVIEW

All of these build-in types are numeric types. Furthermore EXT, DBL, SGL, CXT, CDB and CSG are floating point numbers whereas I64, I32, I16, I8, U64, U32, U16 and U8 are integer numbers. We can divide integers to signed and unsigned integers and floating point numbers to real and complex numers. Indeed these numeric types can be considered to form a conceptual hierarchy similar to one below.

Hierarchy of Numeric Types

Object-oriented programming allows the developer to specify this kind of conceptual hierarchies in software architecture. Each box in the above image can be considered to be a class. Remember from my last article that classes are building blocks in object-oriented programming that encapsulate both data and functionality.

This concept of hierarchies is called inheritance in object-oriented programming. The word inheritance comes from the fact that the classes in the hierarchy inherit properties, functionality and interfaces of their parents and all other ancestors. The diagram itself is called a class diagram as it represents the relations between different classes.

Conclusions

In object-oriented programming developers can define class hierarchies that define the relations of classes. Decedent classes inherit the functionality, the interface and the data type of all the ancestor classes. Although it didn’t yet become clear, class hierarchies and inheritance is one of the key substances in object-oriented programming. Class hierarchies greatly enhance code reuse and allow creating more intuitive software architectures.

In my next article I’ll go into more detail what are the benefits of inheritance. Subscribe to the RSS feed so you will not miss it.

Print This Post Print This Post

Mar
26

Code Reuse with Interface Design and Composition

by Tomi Maila, Mar 26, 2007 at 2:26 pm
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 4.00 out of 5)
Loading ... Loading ...

In my last article I introduced some of the basic concepts behind object oriented programming. Today I continue this introduction by talking about code reuse and composition.

So what do we mean by code reuse? Quoting Wikipedia “Code reuse is the idea that a partial or complete computer program written at one time can be, should be, or is being used in another program written at a later time”. A traditional way in LabVIEW to reuse code is to write subVIs that are shared between many applications or multiple parts of the same application. SubVIs can be further packaged into libraries which contain multiple SubVIs handling different parts of some process.

Object-oriented programming takes code reuse a giant leap forward. The enhanced code reusability is built-in to the design of object oriented programming and was one of the main design goals of object-oriented programming. In my last article I did not mention code reuse. However the concepts I introduced in my last article are central for writing reusable object-oriented code.

Today I’ll concentrate on two concepts of reusing code in object-oriented programming. First code reusability is very much a design issue. In object-oriented programming reusable design is enforced by forcing developers to encapsulate the data and the methods for manipulating the data together into joint entities called classes. As a result programming interfaces become cleaner which as a result increases code reusability. In addition the object data is hidden from the users and only exposed via interface methods forcing developers to think how they classes expose their data to maximize reusability. Second existing classes can be used as private data members of new classes with similar functionality. This way the functionality of a new class can be partially or fully delegated to some other classes.

Object-oriented programming also introduces a powerful technique called inheritance that helps reusing code a great deal. It’s a topic of its own, and we’ll leave it as a subject for our next articles.

 

Designing Reusable Class Interfaces

Although object-oriented programming provides many ways for reusing code, it doesn’t mean that code is automatically reusable. Writing well reusable code requires both experience and a lot of consideration from the developer. An important phase of object-oriented development process is defining the interface for the class under development.

Last time we talked about class interfaces. An interface consists of a set of methods (subVIs) the class user can use to perform actions on an object of that class type. These methods can be for example manipulations of the object private data, getting information about the object state or interacting with other objects or other systems such as files, devices and network. When defining this interface, the developer should think carefully how to make these interface methods as general purpose as possible to allow the class to be used also outside the scope of the current application in development.

In the development process the development team should really concentrate on defining and specifying the central parts of the interface of each class. If the interface of a class is only an implicit result of coding and not a design decision, the code reusability will definitely be scarified.

 

Composition

If a class interface is well designed, the class may be easily used to implement some of the functionality of another class. This can be achieved by using an object of one class type as a private data member of another class. Using classes as private data members of other classes is called composition.

As an example consider a class Engine that represents an engine of a motor vehicle. The interface of Engine has methods Start Engine and Stop Engine. Now consider you would like to create a class Car. Cars normally have engines so you can now use the class Engine as a private data member of class Car.

Composition - Using objects as private data

You may want the interface of class Car have methods Start Car Engine and Stop Car Engine. Now that Engine is a private data member of class Car you can delegate the actions of starting and stopping the engine from the Car class to the Engine class.

Composition - Delegating functionality to member objects

Composition is a very powerful and flexible way of reusing existing code. A new class can be composed of multiple different classes. One class could be used as a private data member multiple times in the same class. In our example class Car could have an array of objects of class Wheel in addition to class Engine as its private data members. Composition even allows changing the underlying implementation at runtime but we will not go deeper in to this dynamic composition yet.

Conclusions

Object oriented programming brings code reuse to completely to a new level. Indeed better code reuse may be the single most important reason to migrate from conventional LabVIEW programming to object-oriented LabVIEW programming. In this articles I’ve introduced several mechanisms of code reuse in object-oriented programming. These seemingly simple concepts are however hard to master. In my future articles I’ll go into more detail how to master these techniques.

In the next article I’ll introduce third mechanism of code reuse called inheritance. Subscribe to the RSS feed not to miss it.

Print This Post Print This Post

Mar
20

Introduction to Objects and Classes

by Tomi Maila, Mar 20, 2007 at 4:01 pm
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 5.00 out of 5)
Loading ... Loading ...

Although object-oriented programming has been a standard method of software development for decades, it’s fairly new concept to most of LabVIEW developers. I start my blog with a series of articles introducing LabVIEW users to the concepts and ideas behind object oriented programming as well as to using object oriented programming in LabVIEW.

You may wonder why you should consider learning object-oriented programming. Well, there are a number of good reasons. Perhaps the most important reason why object-oriented programming has been so successful in the software industry is the fact that people are not very good at mentally managing very complex things. Object-oriented programming allows software architects and developers to divide the problem into more manageable pieces. The advantage is especially clear when working in teams. Each member of the team can concentrate on their own pieces of a complex software entity.

Object-oriented programming allows more modular software design compared to conventional dataflow programming. As a result of modularity object-oriented programming simplifies the modeling of the software architecture. Modularity also makes the software maintenance and management easier and simpler tasks. The software is more manageable throughout the entire lifecycle of the software.

Abstraction

The achieve software modularity object oriented programming relies on the concept of abstraction. The idea is that the software is divided into abstract and independent pieces that are easy to comprehend. Then the actual programming problem is solved using these abstract pieces without the need to know what happens under the hood of these pieces. The abstract pieces help programmers to describe the problem in terms of the problem and not in terms of the solution.

Whereas in traditional LabVIEW programming the abstraction is achieved using subVIs, in object-oriented programming the abstraction is achieved using objects. An object is an entity that fully describes the functionality and the state of something you want to abstract. Consider you want to abstract the concept of a car. An object car would then fully describe the functionality available in the car as well as the state of the car such as color or velocity.

In traditional dataflow programming each wire is of certain type such as a number of type DBL or a cluster composed of a string and a boolean. In a similar way in object-oriented programming in LabVIEW each object is of a certain type, or to be more specific of certain class. Classes are complete definitions of object types in a similar way as typedefs are complete definitions of traditional types.

Interface

Each object in object-oriented programming has an interface that complitely describes the functionality of the object that is available to the user of the object. In LabVIEW the interface is provided with a set of VIs that belong to certain class. Consider for example that you have a class Light that is an abstraction for a light similar to the one on your office table. You can turn on and off the light as well as adjust the brightness of the light. To implement the Light class in LabVIEW, you would need to create a new class called Light.lvclass. You could then define the interface of the class by creating four VIs: on, off, brighten and dim.

Class interface in LabVIEW

Hiding the implementation

When projects become so large that a single person cannot be responsible for the whole project, object-oriented programming becomes a handy tool. In such projects certain developers or class developers can be given a responsibility of developing certain classes. Other developers or class users then use these classes to solve some programming problems.

The interface of the class completely determines how the class user sees the class. The class developer should hide every VI that belongs to the class but that doesn’t belong to the class public interface. The interface VIs should be the only thing exposed to the class user. This concept of hiding parts of the class that do not belong the interface is called hiding the implementation. LabVIEW provides a way to set the visibility of each item belonging to a class from class properties.

Why is hiding the implementation important. Internally very complicated classes can have very simple public interfaces. Hiding the implementation also hides the complicated implementation related issues from the class user and makes the class functionality easier to understand. The interface is something that the developers can agree on before the start of the actual development work allowing developers to work in parallel. Hiding the implementation also prohibits the class user from accidentally using internal parts of the class and this way allows the class developer to change and modify the implementation later on as long as the interface VIs stay the same.

Conclusions

In this article I have discussed the ideas and concepts behind the object-oriented programming and why it is a handy paradigm for software development projects. To summarize dividing the application into abstract pieces called classes make the software projects more manageable compared to subVI level abstraction. Objects are instances of classes and classes specify the type of objects. Each class has a set of public methods called interface that is exposed to the class user. All the rest of the class internal implementation should be hidden from the class user to allow changing the class implementation throughout the lifecycle of the class.

In the next article I’ll dive deeper into the world of object-oriented programming. I’ll talk about reusing classes and about inheritance. Please feel free to comment the article. You may consider signing up to the RSS feed to stay tuned with the forthcoming articles.

Print This Post Print This Post

Get Adobe Flash playerPlugin by wpburn.com wordpress themes