1 templates/generics in c++ and java by: dariusz gawdzik

54
1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

Upload: loren-harvey

Post on 17-Dec-2015

222 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

1

Templates/Generics in C++ and Java

By:

Dariusz Gawdzik

Page 2: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

2

Some Motivation

Suppose you want to develop a general container such as stack in C++ or Java.

One option is to build one container for a specific data type (i.e.. One for integers, one for doubles, one for booleans ).

The following is the implementation of stack that holds integers (parts in red font are due to our choice of the stack’s data type on which it operates ).

Page 3: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

3

IntegerStack.h#pragma once

class IntegerStack{public:

IntegerStack(int capacity);

~IntegerStack(void);

void Push(int i);

int Pop();

int Peek() const;

bool Empty() const;

bool Full() const;

void Print() const;private:

int top;int capacity;int *array;

};

Page 4: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

4

IntegerStack.cpp

#include "integerstack.h"

IntegerStack::IntegerStack(int capacity){

assert(capacity > 0);top = 0;this->capacity = capacity;array = new int[capacity];assert(Empty());

}

IntegerStack::~IntegerStack(void){

delete [] array;}

boolIntegerStack::Empty() const{

return top == 0;}

Page 5: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

5

IntegerStack.cpp (continued )boolIntegerStack::Full() const{

return top == capacity;}intIntegerStack::Peek() const{

return array[top-1];

}

voidIntegerStack::Push(int i) {

assert(! Full());array[top++] = i;assert( ! Empty() );assert( Peek() == i );

}

intIntegerStack::Pop(){

assert(! Empty());return array[--top];

}

Page 6: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

6

How About Stack of Doubles?

We can just modify the stack we already built for integers changing the definitions in red on previous slides from int to double.

Page 7: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

7

How About Stack of Doubles?

Doing it this way would create a lot of stacks one for every data type. Not really a good solution especially if in the future we want to modify the way the stack is implemented. This is a violation of single choice principle which states that a software system that supports a set of alternatives should limit the knowledge of the alternatives to only one module.

Page 8: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

8

How About Stack of Doubles?

But we can do better in C++. We can create a stack that operates on a structure that has as one of its variables union of all the primitive data types available in C++. Also, as one of the fields of the union we add a variable of type void * (this way we can insert any pointer into the structure without explicit cast). So, in fact, we can insert any object we care to create. This is what we want, at least at first sight.

Page 9: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

9

GenericStack.h#pragma once

enum type {INTEGER, CHARACTER, BOOLEAN, DOUBLE_PRECISION, SINGLE_PRECISION, VOID_POINTER };

struct item {

type data_type;

union{

int integer;

//more primitive data types ommited...

char character;

bool boolean;

double double_precision;

float single_precision;

void *void_pointer;

}data;

};

Page 10: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

10

GenericStack.h (continued )class GenericStack

{

public:

GenericStack(int capacity);

~GenericStack(void);

void Push(item i);

item Pop();

item Peek() const;

bool Empty() const;

bool Full() const;

void Print() const;

friend ostream & operator << (ostream &, const item &);

private:

int top;

int capacity;

item *array;

};

Page 11: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

11

GenericStack.cpp#include "genericstack.h"

GenericStack::GenericStack(int capacity)

{

assert(capacity > 0);

top = 0;

this->capacity = capacity;

array = new item[capacity];

assert(Empty());

}

GenericStack::~GenericStack(void)

{

delete [] array;

}

Page 12: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

12

GenericStack.cpp ( continued )

bool

GenericStack::Empty()const{

return top == 0;

}

bool

GenericStack::Full() const{

return top == capacity;

}

item

GenericStack::Peek() const{

return array[top-1];

}

Page 13: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

13

GenericStack.cpp ( continued )

voidGenericStack::Push(item i) {

assert(! Full());array[top++] = i;assert( ! Empty() );

}

itemGenericStack::Pop(){

assert(! Empty());return array[--top];

}

voidGenericStack::Print() const{

cout << "Generic Stack content: " << endl;cout << "|-----------------|"<<endl;for(int i = top-1; i >= 0; i--){

cout << " " << array[i] <<" " << endl;cout << "|-----------------|"<<endl;

}}

Page 14: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

14

GenericStack.cpp (continued )

ostream & operator << (ostream & os, const item & x){

switch (x.data_type ) {case BOOLEAN :

return os <<x.data.boolean;break;

case INTEGER:return os <<x.data.integer;break;

case CHARACTER:return os <<x.data.character;break;

case DOUBLE_PRECISION:return os <<x.data.double_precision;break;

case SINGLE_PRECISION:return os <<x.data.single_precision;break;

case VOID_POINTER:return os <<x.data.void_pointer;break;

default:return os << "unknown data type";

}}

Page 15: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

15

Is the GenericStack the Best We Can Do in C++?The generic stack seems to solve our problem. After all, we have only one stack for all of the data types and the single choice principle is embraced.

But in C++ we can implement a generic stack using templates. Templates are basically classes that require parameter(s) in a similar fashion like functions.

Page 16: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

16

Templates in C++

To take the metaphor a little further. Classes that are not templates are like functions that do not take any parameters.

The parameter for template is provided at a time the template is instantiated.

The parameter resolves ambiguity as to what data type the class/template operates on. This is best understood by using an example (how about stack ).

Page 17: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

17

TemplateStack.h

template <class G>

class TemplateStack

{

public:

TemplateStack(int capacity);

~TemplateStack(void);

void Push(G i);

G Pop();

G Peek() const;

bool Empty() const;

bool Full() const;

void Print() const;

private:

int top;

int capacity;

G *array;

};

#include "TemplateStack.cpp"

Page 18: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

18

TemplateStack.cpp

#include <iostream.h>#include <assert.h>

template <class G>TemplateStack<G>::TemplateStack(int capacity){

assert(capacity > 0);top = 0;this->capacity = capacity;array = new G[capacity];

assert(Empty());}

template <class G>TemplateStack<G>::~TemplateStack(void){

delete [] array;}

template <class G>boolTemplateStack<G>::Empty()const{

return top == 0;}

Page 19: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

19

TemplateStack.cpp ( continued )

template <class G>boolTemplateStack<G>::Full() const{

return top == capacity;}

template <class G>GTemplateStack<G>::Peek() const{

return array[top-1];

}

template <class G>voidTemplateStack<G>::Push(G i) {

assert(! Full());

array[top++] = i;

assert( ! Empty() );}

Page 20: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

20

TemplateStack.cpp (continued )

template <class G>GTemplateStack<G>::Pop(){

assert(! Empty());return array[--top];

}

template <class G>voidTemplateStack<G>::Print() const{

cout << "Generic Stack content: " << endl;cout << "|-----------------|"<<endl;for(int i = top-1; i >= 0; i--){

cout << " " << array[i] <<" " << endl;cout << "|-----------------|"<<endl;

}}

Page 21: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

21

The syntax of template Declaration

The class declaration in .h file is preceded with keyword:

template <class G>

The alternate keyword supported by some compilers is template <typedef G>

Page 22: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

22

The G is the formal generic parameter in which place we will put a data type when we instantiate the class.The class keyword in a misnomer the actual parameter need not be a class but can in fact be a primitive type as well; hence the better name typedef supported by some compilers.We need to place the #include “TemplateStack.cpp”At the end of TemplateStack.h file.

Page 23: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

23

In our class we put the generic parameter G where we regularly would put a data type on which stack operates.

We can instantiate the template stack as we would a normal class except we provide the generic parameter.

Page 24: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

24

#include <stdio.h>#include "TemplateStack.h"

int main(int argc, char* argv[]){

TemplateStack<double> *tStack = new TemplateStack<double>(20);

tStack->Push(13.2);tStack->Push(2.0);tStack->Push(1.12);tStack->Print();

TemplateStack<char *> *chStack = new TemplateStack<char *>(20);chStack->Push("nice");chStack->Push("are");chStack->Push("templates");chStack->Print();

return 0;}

Page 25: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

25

Script started on Mon Mar 22 16:41:02 20042;red:/cs/home/cs973269/cs4301/A3/C++/build 301 build % main

Generic Stack content: |-----------------| 1.12 |-----------------| 2 |-----------------| 13.2 |-----------------|

Generic Stack content: |-----------------| templates |-----------------| are |-----------------| nice |-----------------|

302 build % exit exitscript done on Mon Mar 22 16:41:11 2004

Page 26: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

26

How about Java?

If you think that Java is a much better language than C++ you may say that all the complexities of templates can be avoided, if as in Java, we have a class hierarchy where Object is the ultimate ancestor of all classes.

In Java collections such as stack are implemented to operate on Objects.

Page 27: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

27

Java’s Approach

Let’s have a look at Java collections and see if we can find some problems with this approach.

First of all, we can only insert Objects into Java collections which leaves primitive types and arrays out of the loop.

Page 28: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

28

Java’s Approach

Yes, we can use wrapper classes for primitive types but this provides for slower executing programs and gives programmers another thing to take care of.

But the biggest problem is with static typing.

Let me illustrate what I mean by the previous statement.

Page 29: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

29

import java.util.Stack;

class Main{

public static void main(String[] args) {

Stack st = new Stack();st.push(new Integer(1));st.push(new String("good"));

Integer i = (Integer) st.pop();

System.out.println(st);}

}

% java Main Exception in thread "main" java.lang.ClassCastException

at Main.main(Main.java:12)

Page 30: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

30

Java and Static typing

The pervious program had a semantic bug in it. I suppose the programmer wanted to use the stack for integers and by mistake inserted the string.

The exception was raised by JVM at run time and, in this case, it caused the entire system to crush.

Page 31: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

31

Java and static typing

In this case no damage done, but imagine you are writing application for auto pilot in an air plane.

You don’t want this kind of semantic bug to crush the plane nor do you want to provide for any imaginable possibility in your exception handler.

Page 32: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

32

Java and static typing

The fact is, the semantic bugs are the hardest to find and to recover from. On many occasions you will not be able to provided for recovery in the exception handler.

Ideally we would want this kind of bug to be caught at compile time.

Page 33: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

33

Java versus C++

Java is an improvement over C++ in many respects but not in all respects unfortunately.

The following code is the equivalent of Java code that caused our system to crush. It uses our TemplateStack.

Page 34: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

34

#include "TemplateStack.h"

int main(int argc, char* argv[]){

//testing template stackTemplateStack<int> *iStack = new TemplateStack<int>(20);

iStack->Push(1);iStack->Push(2);iStack->Push("some string");iStack->Print();

return 0;}

../prog/Main.cpp: In function `int main(int, char **)':

../prog/Main.cpp:17: no matching function for call to `TemplateStack<int>::Push (char[12])'

../lib/TemplateStack.cpp:41: candidates are: void TemplateStack<int>::Push(int)make: *** [Main.o] Error 1

Page 35: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

35

Java versus C++

So the error that caused our system to crush miserably in Java was detected in C++ through the use of template class at compile time (before we released the auto pilot module that caused the plane to crush and us to get fired ).

Can we do anything to correct that Java deficiency?

Page 36: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

36

Java and templates

According to Sun Microsystems Inc. adding Generics (templates) to Java is one of the most requested extensions to the language: “This feature is one of the most frequently requested language extensions on the JDC (no. 7 on the bug parade - no. 2 among language extensions). “ (http://java.sun.com/developer/techDocs/Newsletters/2002/nl1113.html)

Page 37: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

37

Java 1.5

With Java 1.5, still in Beta version, we get the support for Generics.

Lets have a look at the basic syntax which is somewhat similar to the syntax of C++.

Page 38: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

38

public class GenericStack<G> {

/* Public Part */

GenericStack(int capacity){

assert(capacity > 0);

top = 0;

this.capacity = capacity;

array = new Object[capacity];

assert(Empty());

}

public boolean Empty(){

return top == 0;

}

public boolean Full() {

return top == capacity;

}

public G Peek() {

return (G) array[top-1];

}

Page 39: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

39

public void Push(G i) {assert(! Full());

array[top++] = i;assert( ! Empty() );

}

public G Pop(){assert(! Empty());

return (G) array[--top];}

public void Print(){System.out.println("Generic Stack content: ");System.out.println("|-----------------|");for(int i = top-1; i >= 0; i--){

System.out.println(" " + array[i] +" ");System.out.println("|-----------------|");

}}/* Private Part */private int top;private int capacity;private Object[] array;

}

Page 40: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

40

Some pointsFirst the java syntax is shorter we just need to add <G> to the class definition.There is some deficiency of implementation: we can’t define G[] array like we could in C++.This results in defining array of Objects for private implementation and then casting to (G) whenever we return value from that array.When compiling we need to add –source 1.5 switch to javac otherwise the new syntax will create compile time errors.

Page 41: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

41

class Main {

public static void main(String[] args) {

GenericStack<Integer> st = new GenericStack<Integer>(20);

st.Push(1);

st.Push(2);

st.Push(3);

st.Print();

GenericStack<String> s = new GenericStack<String>(20);

s.Push("Java 1.5");

s.Push("in");

s.Push("Generics");

s.Print();

}

}

Page 42: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

42

Generic Stack content:

|-----------------|

3

|-----------------|

2

|-----------------|

1

|-----------------|

Generic Stack content:

|-----------------|

Generics

|-----------------|

in

|-----------------|

Java 1.5

|-----------------|

Page 43: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

43

Java and generics

The introduction of generics allows as to define homogeneous containers of which until now array was the only representative.

But what happens when we want to define a container that is not homogeneous.

Page 44: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

44

Java and Generics

Of course there is a simple solution create Stack<Object>

How about inheritance and generics can we do this:

List<String> s_list = new ArrayList<String>();

List<Object> o_list = s_list; // is a list of string a // list of object?

Page 45: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

45

Java and Generics

As it turns out we can’t the compiler will issue incompatible types error.

If we could then this code would generate error as well.

o_list.add(new Object());

String s = o_list.get(0);

Page 46: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

46

Java and Generics

What if we want to specify that our method takes a stack that has a generic actual parameter that can be a base or derived class of certain type (doing Stack<SomeType> will not work as you saw previously since Stack<SomeType> is not a parent of Stack<Child of SomeType> )

void method( Stack<“what goes here?”> arg) {….}

Page 47: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

47

Java and Generics

Two solutions:

Define it as:

void method(Stack<? extends Type> arg ){..}

Define it as

void method(Stack<?> arg){...}

where ? Is a wild card which specifies any type (so method can operate on any stack what so ever).

Page 48: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

48

Java 1.5

Java 1.5 to be soon released makes major changes to the language.Besides adding generics it introduces boxing/unboxing for primitive types so that we no longer have to have wrapper classes.It introduces new for loop constructIt introduces variable arguments to the functions.It finally introduces enum data type.

Page 49: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

49

Short preview

Variable arguments//args is of type Object[]

void argtest(Object ... args) { for (int i=0;i <args.length; i++) { System.out.println(args[i] );}

}

argtest("test", "data");

Page 50: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

50

Short preview

Enumerations

public enum StopLight { red, amber, green };

Page 51: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

51

Short previewNew for loop for iterators

Before:

ArrayList<Integer> list = new ArrayList<Integer>(); for (Iterator i = list.iterator(); i.hasNext();) {

Integer value=(Integer)i.next();

}

After:ArrayList<Integer> list = new ArrayList<Integer>();

for (Integer i : list) {

Integer value=(Integer)i.next();

}

Page 52: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

52

Some Theory Behind Generics

Generics allow to abstract over types.

In object oriented programming class is viewed as a merge of the notion of module and type. So, if we don’t have genericity then every class is a module that is also a type.

With generics a class defined as Stack<G> is a type pattern covering an infinite set of possible types which are obtained by providing the actual generic parameter G.

Page 53: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

53

References:

http://java.sun.com/j2se/1.5/pdf/Tiger-lang.pdf

Object-Oriented Software Construction (2nd ed) by Bertrand Meyer. (Bible for OOP).

http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

Page 54: 1 Templates/Generics in C++ and Java By: Dariusz Gawdzik

54

Thank You

The End.