Block Structured

Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

Properties of an identifier (and the Example:

object it represents) may be set at


• Compile-time In Fortran
• The scope of an identifier is the whole
These are static properties as program or subprogram.
they do not change during
execution. Examples include • Each identifier may be declared only
once.
the type of a variable, the value
of a constant, the initial value • Variable declarations may be implicit.
of a variable, or the body of a (Using an identifier implicitly declares
it as a variable.)
function.
• The lifetime of data objects is the
• Run-time
whole program.
These are dynamic properties.
Examples include the value of a
variable, the lifetime of a heap
object, the value of a function’s
parameter, the number of times
a while loop iterates, etc.

© ©
CS 538 Spring 2008 44 CS 538 Spring 2008 45

Block Structured Languages Binding of an identifier to its


corresponding declaration is
• Include Algol 60, Pascal, C and Java. usually static (also called
• Identifiers may have a non-global lexical), though dynamic
scope. Declarations may be local to a binding is also possible.
class, subprogram or block.
Static binding is done prior to
• Scopes may nest, with declarations execution—at compile-time.
propagating to inner (contained)
scopes. Example (drawn from C):
• The lexically nearest declaration of an
identifier is bound to uses of that int x,z;
identifier. void A() {
float x,y;
print(x,y,z);
int
} float
void B() { float
print (x,y,z)
int
} undeclared
int

© ©
CS 538 Spring 2008 46 CS 538 Spring 2008 47
Block Structure Concepts Variations in these rules of
name scoping are possible.
• Nested Visibility
For example, in Java, the
No access to identifiers outside lifetime of all class objects is
their scope. from the time of their creation
• Nearest Declaration Applies (via new) to the last visible
Static name scoping. reference to them.
• Automatic Allocation and Deallocation Thus
of Locals ... Object O;...
Lifetime of data objects is creates an object reference but
bound to the scope of the does not allocate any memory
Identifiers that denote them. space for O.
You need
... Object O = new Object(); ...
to actually create memory
space for O.

© ©
CS 538 Spring 2008 48 CS 538 Spring 2008 49

Dynamic Scoping Example:


An alternative to static scoping int x;
is dynamic scoping, which was void print() {
used in early Lisp dialects (but write(x); }
not in Scheme, which is main () {
statically scoped). bool x;
Under dynamic scoping, print();
identifiers are bound to the }
dynamically closest declaration Under static scoping the x
of the identifier. Thus if an written in print is the lexically
identifier is not locally closest declaration of x, which
declared, the call chain is as an int.
(sequence of callers) is
examined to find a matching Under dynamic scoping, since
declaration. print has no local declaration
of x, print’s caller is examined.
Since main calls print, and it
has a declaration of x as a bool,
that declaration is used.

© ©
CS 538 Spring 2008 50 CS 538 Spring 2008 51
Dynamic scoping makes type Virtual Functions
checking and variable access
harder and more costly than A function declared in a class,
static scoping. (Why?) C, may be redeclared in a class
derived from C. Moreover, for
However, dynamic scoping
uniformity of redeclaration, it is
does allow a notion of an
important that all calls,
“extended scope” in which
including those in methods
declarations extend to
within C, use the new
subprograms called within that
declaration.
scope.
Example:
Though dynamic scoping may class C {
seen a bit bizarre, it is closely void DoIt()(PrintIt();}
related to virtual functions void PrintIt()
{println(“C rules!”);}
used in C++ and Java. }
class D extends C {
void PrintIt()
{println(“D rules!”);}
void TestIt() {DoIt();}
}
D dvar = new D();
dvar.TestIt();
D rules! is printed.

© ©
CS 538 Spring 2008 52 CS 538 Spring 2008 53

Scope vs. Lifetime In C:


void p() {
It is usually required that the static int i = 0;
lifetime of a run-time object at print(i++);
least cover the scope of the }
identifier. That is, whenever Each call to p prints a different
you can access an identifier, the value of i (0, 1, ...) Variable i
run-time object it denotes retains its value across calls.
better exist.
Some languages allow an
But, explicit binding of an identifier
it is possible to have a run-time for a fixed scope:
object’s lifetime exceed the Let {
scope of its identifier. An id = val type id = val;
example of this is static or own in statements
variables. statements }
end;
A declaration may appear
wherever a statement or
expression is allowed. Limited
scopes enhance readability.

© ©
CS 538 Spring 2008 54 CS 538 Spring 2008 55
Structs vs. Blocks Blocks and structs look similar,
but there are significant
Many programming languages, differences:
including C, C++, C#, Pascal
Structs are data,
and Ada, have a notion of
grouping data together into • As originally designed, structs
contain only data (no functions or
structs or records.
methods).
For example: • Structs can be dynamically created,
struct complex { float re, im; } in any number, and included in
other data structures (e.g., in an
There is also the notion of
array of structs).
grouping statements and
declarations into blocks: • All fields in a struct are visible
outside the struct.
{ float re, im;
re = 0.0; im = 1.0;
}

© ©
CS 538 Spring 2008 56 CS 538 Spring 2008 57

Blocks are code, Classes


• They can contain both code and
data. • Class objects can be created as
needed, in any number, and included
• Blocks can’t be dynamically created in other data structure.
during execution; they are “built
into” a program. • They include both data (fields) and
functions (methods).
• Locals in a block aren’t visible
outside the block. • They include mechanisms to initialize
themselves (constructors) and to
By adding functions and finalize themselves (destructors).
initialization code to structs, • They allow controlled access to
we get classes—a nice blend of members (private and public
structs and blocks. declarations).
For example:
class complex{
float re, im;
complex (float v1, float v2){
re = v1; im = v2; }
}

© ©
CS 538 Spring 2008 58 CS 538 Spring 2008 59
Type Equivalence in Classes Then we may not want
assignment to be allowed.
In C, C++ and Java, instances of
the same struct or class are class Point {
type-equivalent, and mutually int dimensions;
assignable. float coordinates[];
Point () {
For example: dimensions = 2;
class MyClass { ... } coordinates = new float[2];
}
MyClass v1, v2;
Point (int d) {
v1 = v2; // Assignment is OK dimensions = d;
coordinates = new float[d];
}
}
We expect to be able to assign Point plane = new Point();
values of the same type, Point solid = new Point(3);
including class objects. plane = solid; //OK in Java

However, sometimes a class


models a data object whose This assignment is allowed,
size or shape is set upon even though the two objects
creation (in a constructor). represent points in different
dimensions.

© ©
CS 538 Spring 2008 60 CS 538 Spring 2008 61

Subtypes Parametric Polymorphism


In C++, C# and Java we can We can create distinct
create subclasses—new classes subclasses based on the values
derived from an existing class. passed to constructors. But
We can use subclasses to create sometimes we want to create
new data objects that are subclasses based on distinct
similar (since they are based on types, and types can’t be
a common parent), but still passed as parameters. (Types
type-inequivalent. are not values, but rather a
property of values.)
Example:
We see this problem in Java,
class Point2 extends Point {
which tries to create general
Point2() {super(2); } purpose data structures by
}
basing them on the class
class Point3 extends Point {
Object. Since any object can be
Point3() {super(3); }
}
assigned to Object (all classes
Point2 plane = new Point2(); must be a subclass of Object),
Point3 solid = new Point3(); this works—at least partially.
plane = solid; //Illegal in Java

© ©
CS 538 Spring 2008 62 CS 538 Spring 2008 63
class LinkedList { • We must use wrapper classes like
Object value; Integer rather than int (because
LinkedList next; primitive types like int aren’t
Object head() {return value;} objects, and aren’t subclass of
LinkedList tail(){return next;} Object).
LinkedList(Object O) {
value = O; next = null;} For example, to use LinkedList
LinkedList(Object O, to build a linked list of ints we
LinkedList L){ do the following:
value = O; next = L;}
} LinkedList l =
new LinkedList(new Integer(123));
Using this class, we can create int i =
a linked list of any subtype of ((Integer) l.head()).intValue();
Object. This is pretty clumsy code.
But, We’d prefer a mechanism that
• We can’t guarantee that linked lists
allows us to create a “custom
are type homogeneous (contain version” of LinkedList, based
only a single type). on the type we want the list to
• We must cast Object types back
contain.
into their “real” types when we
extract list values.

© ©
CS 538 Spring 2008 64 CS 538 Spring 2008 65

We can’t just call something like Thus we have


LinkedList(int) or class LinkedList<T> {
LinkedList(Integer) because T value; LinkedList<T> next;
T head() {return value;}
types can’t be passed as
LinkedList<T> tail() {
parameters. return next;}
Parametric polymorphism is LinkedList(T O) {
value = O; next = null;}
the solution. Using this LinkedList(T O,LinkedList<T> L)
mechanism, we can use type {value = O; next = L;}
}
parameters to build a “custom LinkedList<int> l =
version” of a class from a new LinkedList(123);
general purpose class. int i = l.head();
C++ allows this using its
template mechanism. Tiger Java
also allows type parameters.
In both languages, type
parameters are enclosed in
“angle brackets” (e.g.,
LinkedList<T> passes T, a type,
to the LinkedList class).

© ©
CS 538 Spring 2008 66 CS 538 Spring 2008 67

You might also like