UNU/IIST International Institute for Software Technology
Modelling Object-oriented Programming with Reference Type and Dynamic Binding He Jifeng, Liu Zhiming and Li Xiaoshan May, 2003
UNU/IIST Report No. 280
R
UNU/IIST and UNU/IIST Reports UNU/IIST (United Nations University International Institute for Software Technology) is a Research and Training Centre of the United Nations University (UNU). It is based in Macau, and was founded in 1991. It started operations in July 1992. UNU/IIST is jointly funded by the Governor of Macau and the governments of the People’s Republic of China and Portugal through a contribution to the UNU Endownment Fund. As well as providing two-thirds of the endownment fund, the Macau authorities also supply UNU/IIST with its office premises and furniture and subsidise fellow accommodation. The mission of UNU/IIST is to assist developing countries in the application and development of software technology. UNU/IIST contributes through its programmatic activities: 1. Advanced development projects, in which software techniques supported by tools are applied, 2. Research projects, in which new techniques for software development are investigated, 3. Curriculum development projects, in which courses of software technology for universities in developing countries are developed, 4. University development projects, which complement the curriculum development projects by aiming to strengthen all aspects of computer science teaching in universities in developing countries, 5. Schools and Courses, which typically teach advanced software development techniques, 6. Events, in which conferences and workshops are organised or supported by UNU/IIST, and 7. Dissemination, in which UNU/IIST regularly distributes to developing countries information on international progress of software technology. Fellows, who are young scientists and engineers from developing countries, are invited to actively participate in all these projects. By doing the projects they are trained. At present, the technical focus of UNU/IIST is on formal methods for software development. UNU/IIST is an internationally recognised center in the area of formal methods. However, no software technique is universally applicable. We are prepared to choose complementary techniques for our projects, if necessary. UNU/IIST produces a report series. Reports are either Research R , Technical T , Compendia C or Administrative A . They are records of UNU/IIST activities and research and development achievements. Many of the reports are also published in conference proceedings and journals. Please write to UNU/IIST at P.O. Box 3058, Macau or visit UNU/IIST’s home page: http://www.iist.unu.edu, if you would like to know more about UNU/IIST and its report series.
Chris George, Acting Director
UNU/IIST International Institute for Software Technology
P.O. Box 3058 Macau
Modelling Object-oriented Programming with Reference Type and Dynamic Binding He Jifeng, Liu Zhiming and Li Xiaoshan Abstract This report aims to develop mathematical characterisations of object-oriented concepts, and provide a proper semantic basis essential for ensuring correctness and for the development of tools to support the use of formal techniques. We present an observation-oriented semantics for an object-oriented language with a rich variety of features, including subtype, visibility, inheritance, dynamic binding and polymorphism. The language is sufficient similar to Java and C++ used in meaningful case studies and to capture some of the central difficulties. Our approach has mostly been influenced by the development of the design calculus based on the standard predicate logic. The difference is that states are encoded as a mapping from variables to sequences of values in coping with nested declaration of variables. The approach also considers object names as values and mutually dependent methods.
He Jifeng is a senior research-fellow of UNU/IIST. He is also a professor of computer science at the Software Engineering Institute of East China Normal University. His research interests include the theories of programming languages, formal methods for safety-critical systems, parallel and distributed systems, component-oriented computing, co-design techniques for real-time embedded systems. Email:
[email protected] Liu Zhiming is a research fellow at UNU/IIST, on leave from Department of Mathematics and Computer Science of the University of Leicester, England, where he is a lecturer in computer science. His research interests include theory of computing systems, formal methods for specification, verification and refinement of fault-tolerant, real-time and concurrent systems; and formal techniques for OO development. Email:
[email protected] Li Xiaoshan is an Associate Professor at the University of Macao. His research areas are Interval Temporal Logic, formal specification, verification and simulation of computer systems, formal methods in system design and implementation. Email: fstxsl@umac,mo
c 2003 by UNU/IIST, He Jifeng, Liu Zhiming and Li Xiaoshan Copyright °
Contents
i
Contents 1 Introduction
1
2 A state-based model 2.1 Programs are design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Features of Object-oriented Programming . . . . . . . . . . . . . . . . . . . . . .
2 2 3
3 Expression
5
4 Commands
7
5 Class Declarations 5.1 Class declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Definition of a declaration section . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Formalisation of methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10 10 11 13
6 Conclusion
14
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Introduction
1
1
Introduction
Software engineering aims to develop software by using approaches which enable large and complex program suites to be developed in a systematic way. However it is well known that it is hard to obtain the level of assurance of correctness for safety critical software using old fashioned programming techniques. In the search for techniques for making software cheaper and more reliable, two important but largely independent influences have been visible in recent years. They are • Object-oriented Programming • Formal Methods First, it becomes evident that objects are, and will remain an important concept in software. Experimental languages of the 1970’s introduced various concepts of package, cluster, module, etc, giving concrete expression to the importance of modularity and encapsulation, the construction of software components hiding their state representations and algorithmic mechanisms from users, exporting only those features which were needed in order to use the objects. This gives the software components a level of abstraction, separating the view of what a module does for the system from the details of how it does them. It is also clear that certain properties of objects, particular inheritance and the use of object references as part of the data stored by an object, could be used to construct large systems incrementally, as well as making it possible to reuse objects in different contexts. At least for highly critical software systems, it seems essential to give software engineering the same basis in mathematics that is the hall mark of other important engineering disciplines. In this there has been much progress, resulting in three main paradigms: model-based, algebraic and process algebra. Both practitioners of formal methods and experts in object technology have investigated how formal specification can supplement object-oriented development, or how it may help to clarify the semantics of object-oriented notations and concepts. Examples of such work include formalisation of the OMG’s core object [15] model using Z [21], formalisation of the OOA notation using Z. The work on OOA uncovered apparent weakness in its semantics, such as the lack of any relationship between the set of object identifiers of instances of a subtype and those of its supertypes. Model-based formalisms have been used extensively in conjunction with object-oriented techniques, via languages such as Object-Z [5], V DM ++ [11], and methods such as Syntropy [9] (which uses Z notation) and Fusion [7, 8] (related to V DM ). Whilst these formalisms are effective at modelling data structures, as sets and relations between sets, they are not ideal for capturing more sophisticated object-oriented mechanisms, such as dynamic binding and polymorphism. Cavalcanti and Naumann define an object-oriented programming language with subtype and polymorphism is using predicate transformer [6, 18]. Sekerinski [17, 20] defines a rich objectoriented language by using a type system with subtyping and as well as predicate transformer.
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
A state-based model
2
However, neither reference type nor mutual dependency between classes is allowed in those approaches. Rustin and Leino [19] have extended existing refinement calculi with object-oriented features, but restricting inheritance or not dealing with class and visibility. This report aims to develop mathematical characterisations of object-oriented concepts, and provide a proper semantic basis essential for ensuring correctness and for the development of tools to support the use of formal techniques. We define an object-oriented language with subtype, visibility, reference type, inheritance, dynamic biding and polymophism. The language is sufficient similar to Java and C++ used in meaningful case studies and to capture some of the central difficulties. We build a logic of object-oriented program as a conservative extension of standard predicate logic [14]. In our model, both commands and class declarations are identified as a predicate, whose alphabet includes logic variables representing the initial and final values of program variables, and as well as those representing the contextual information of classes and their links. Our framework allows variables to be redefined in its scope. Consequently, their states will usually comprise a sequence of values. A variable of the primitive types stores the data of the corresponding types, whereas objects can hold object references as its state. This report will define the traditional programming constructs, such as conditional, sequential composition and recursion in the exactly same way as their counterpart in the imperative programming languages without reference types. This makes our approach more accessible to users who are already familiar with the existing imperative languages.
2
A state-based model
This section devices a state-based model for an object-oriented language with subtype, inheritance, reference type, and dynamic binding and polymorphism. We begin with a standard predicate logic for the imperative languages, and point out its weakness in dealing with dynamic features of object technology. Finally, we select a list of logic variables which provide all the environment information needed to support execution of object-oriented programs.
2.1
Programs are design
In [14], a program is identified as a design , which is represented by a pair (α, P ), where • α denotes the set of accessible program variables. • P is a predicate of the form p(x) ` R(x, x0 ) =df (ok ∧ pre(x)) ⇒ (ok 0 ∧ R(x, x0 )) where x and x0 stand for the initial and final values of program variables x, and the predicate p, called precondition, characterises those initial states in which the activation of
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
A state-based model
3
the program will lead its execution to termination. The predicate R, called post-condition, relates the initial states of the program to its final states. We describe the termination behaviour of a program by the Boolean variables ok and ok 0 , where the former is true if the program is properly activated, whereas the latter becomes true if the execution of the program terminates successfully. For simplicity, that model adopts a universal data type, and allows neither reference type nor nested declaration. Notations (design with a frame) Let V be a set of variables, then the notation V : (p ` R) denotes the design p ` (R ∧ w0 = w)) where the list w contains all variables but those in the set V . V is called the frame of the design (p ` R).
2.2
Features of Object-oriented Programming
To formalising the behaviour of object-oriented programs, we have to take into account the following features: • A program operates not only on variables of primitive types, but also objects of reference types. • To protect attributes from illegal access, the model has to address the problem of visibility of attributes to the environment. • An object can be associated with any subclass of its originally declared one. To validate expressions and commands in a dynamic binding environment, the model must keep track of the current type for each object. Our approach describes the behaviour of an object-oriented program by a design equipped the following logical variables as its free variables
1. cname: the set of classes which are defined so far. 2. Each class C ∈ cname is ascribed by (2.1) attr(C): the set of its (declared or inherited) attributes.
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
A state-based model
4
{< a1 : T1 , d1 >, ... , < am : Tm , dn >} where Ti and di are the type and initial value of attribute ai , and will later be referred by decltype(C.ai ) and initial(C.ai ). (2.2) op(C): the set of its (declared and inherited) methods. {m1 7→ (val 7→< x1 : T1, 1 >, valres 7→< y1 : T1.2 >, res 7→< z1 : T1.3 >, def 7→ D1 ), ..., mk 7→ (val 7→< xk : Tk, 1 >, valres 7→< yk : Tk.2 >, res 7→< zk : Tk.3 >, def 7→ Dk )} which states that the method mi has xi , yi and zi as its value, result and value-result parameters respectively, which will be referred by val(C.mi ), res(N.mi ) and valres(C.mi ) later, and its behaviour is defined by the design Di . 3. superclass :: the partial function mapping a class to its direct superclass. 4. var: the set of variables which are known to the program. Since our language permits nested declaration, var associates each variable with a sequence of types {(x1 , < T1.1 , ..., T1,m >), ..., (xi , < Ti,1 , ..., Ti, n >), ... , (xn , < Tn,1 , ..., Tn,k >)} where Ti,1 , representing the most recently declared type of variable xi , will be referred by decltype(xi ) later. For simplicity we abuse the notation by writing x ∈ var to abbreviate x ∈ π1 (var). where the projection π1 maps each pair to its first element. We will also use var(x) to denote the sequence of types associated with x. 5. visibleattr: the set of attributes which are visible from inside the current class, i.e, all its declared attributes plus the public and protected attributes inherited from its superclasses. 6. x: the state of variable x. Since a variable can be redefined, its state usually comprises a nonempty finite sequence of values, whose first element represents the current value of the variable. A variable of a primitive data type can take any member of that type as its value. However, an object variable can store an object name as its value. For any logic variables v defined previously, we will use v and v 0 to stand for its initial and final state. Notations Class C is said to be a subclass of C 0 (denoted by C ¹ C 0 ), if either C = C 0 , or there exists a finite family {Ci | 0 ≤ i ≤ n} of classes such that C = C0 and C 0 = Cn and superclass(Ci ) = Ci+1 for 0 ≤ i < n Let s be a non-empty sequence. We use head(s) to denote its first element, and tail(s) the sequence s after removal of its first element.
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Expression
3
5
Expression
This section shows how to validate an expression and determine its value. Variables which can appear in the left hand side of an assignment, are of the following forms le ::= x | le.a | self Definition 3.1 Let le1 and le2 be object expressions. We say le1 refers directly to le2 , (denoted by le1 → le2 ), if its current value is a reference to le2 le1 → le2 =df head(le1 ) = le2 Define le1 =⇒ le2 =df (le1 →∗ le2 ) ∧ head(le2 ) = le2 which states that it is the object le2 which holds the current value of le1 . As a result, le1 has the declared type of le2 as its current type. We will use le1 =⇒ to denote the Boolean expression ∃le2 • le1 =⇒ le2 2 A variable x is well-defined if it is known to the program and its most recently declared type is a primitive type or an already defined class. x ∈ var ∧ WD(x) =df (decltype(x) is a primitive type ∨ decltype(x) ∈ cname ∧ x =⇒) Its current type is defined by ( decltype(x) type(x) =df decltype(o)
decltype(x) is a primitive type x =⇒ o
An attribute le.a is well-defined when le is a non-null object, and its a-attribute is visible within the current environment. Let M and N be the declared and current types of le respectively, then WD(le.a) =df WD(le) ∧ (head(le) 6= null) ∧ (N.a ∈ visibleattr) The declared and current types of le.a are defined by decltype(le.a) =df
decltype(M.a)
type(le.a) =df
decltype(N.a)
self is used to refer to the object whose methods are currently activated. WD(self) =df type(self) =df
Report No. 280, May, 2003
self ∈ var ∧ self =⇒ decltype(o) where self =⇒ o
UNU/IIST, P.O. Box 3058, Macau
Expression
6
Expressions, which can appear on the right hand side of assignment , are generated by the following rules: e ::= x | le.a | null | e is C | (C)e | f (e) We use value(e) to denote the result yielded by evaluation of expression e. For an assignable expression, its evaluation may yield a reference if it is an object. ( head(x) decltype(x) is a primitive type value(x) =df x decltype(x) ∈ cname ( head(o.a) decltype(le.a) is a primitive type and le =⇒ o value(le.a) =df le.a decltype(le.a) ∈ cname The reserved identifier null represents a well-defined object. WD(null) =df type(null) =df value(null) =df
true N U LL null
where N U LL is a reserved class name. We adopt the convention that N U LL ¹ C for all classes C. A type test e is C is well-defined when C is an already declared class, and e is a well-defined object. WD(e is C) =df type(e is C) =df value(e is C) =df
WD(e) ∧ (decltype(e) ∈ cname) ∧ (C ∈ cname) Bool type(e) 6= N U LL ∧ type(e) ¹ C
A type cast (C)e is well-defined, if e lies in class C. WD((C)e) =df
WD(e is C) ∧ value(e is C)
type((C)e) =df
type(e)
value((C)e) =df
value(e)
The following exemplifies the well-definedness of built-in expressions WD(e/f) =df
WD(e) ∧ (type(e) = Real) ∧ WD(f) ∧ (type(f) = Real) ∧ (value(f) 6= 0)
WD(e ∧ f ) =df
Report No. 280, May, 2003
WD(e) ∧ (type(e) = Bool) ∧ WD(f) ∧ (type(f) = Bool)
UNU/IIST, P.O. Box 3058, Macau
Commands
4
7
Commands
This section deals with commands. Our language supports typical object-oriented programming constructs: c ::= skip
termination
| le = e
assignment
| chaos
abort
| c¢b¤c
conditional
|cuc
non-determinism
| c; c
sequence
| b∗c
iteration
| var x : T = e
declaration
| end x
undeclaration
| le.m(e)
method call
| C.N ew(x)
creation of new object
The program skip does nothing, and terminates successfully. skip =df ∅ : (true ` true) The execution of x = e assigns the value of e to x. It is well-defined if both x and e are well-defined, and the current type of e matches the declared type of x, and furthermore the assignment will not introduce cyclic reference. WD(x) ∧ WD(e) ∧ (type(e) ¹ decltype(x)) ∧ ` (x0 = < value(e) > ·tail(x)) x = e =df {x} : decltype(x) ∈ cname ⇒ (¬(e →∗ x) ∧ (e =⇒)) Assignment self = e is defined in the same way as x = e. The execution of le.a = e assigns the value of e to the a-attribute of the object o to which le refers. le.a = e =df
WD(le.a) ∧ WD(e) ∧
(type(e) ¹ decltype(le.a)) ∧ le=⇒o {o.a} : decltype(le.a) ∈ cname ⇒
W
` (o.a0 =< value(e) > ·tail(o.a))
(¬(e →∗ le.a) ∧ (e =⇒))
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Commands
8
chaos represents the most unpredictable program. chaos =df ∅ : (f alse ` true) The notation P ¢ b ¤ Q describes a program which behaves like P if the initial value of b is true, or like Q if the initial value of b is false. P ¢ b ¤ Q =df (WD(b) ∧ type(b) = Bool) ⇒ (P ∧ value(b) ∨ Q ∧ ¬value(b)) Let {Pi | 1 ≤ i ≤ n} be a family of programs, and {bi | 1 ≤ i ≤ n} a family of Boolean expressions. The notation if {(bi → Pi ) | 1 ≤ i ≤ n} fi represents a program, which selects Pi to execute if its guard bi is true. When all the guards are false it behaves chaotically if {(bi → Pi ) | 1 ≤ i ≤ n} fi =df V W V i (WD(bi ) ∧ type(bi ) = Bool) ⇒ ( i (value(bi ) ∧ Pi ) ∨ ( i ¬value(bi ) ∧ chaos) The notation P u Q denotes a program which is executed by executing either P or Q but with no indication which one will be chosen. P u Q =df P ∨ Q P ; Q describes a program which may be executed by first executing P , and when P terminates then Q is started. The final state of P is passed on as the initial state of Q. P (s, s0 ); Q(s, s0 ) =df ∃m • P (s, m) ∧ Q(m, s0 ) Let P be a program and b a Boolean condition, the notation b ∗ P denotes a program which repeats the program P as long as b is true before each iteration. b ∗ P =df µX • (P ; X) ¢ b ¤ skip where µX • F (X) stands for the weakest fixed point [22] of the recursive equation X = F (X). To introduce a new program variable v we use the form of declaration var v : T which permits the variable v of type T to be used in the portion of the program that follows it. The complementary operation (called undeclaration) takes the form end v, and terminates the region of permitted use of v. Formally, the declaration and undeclaration are defined by var x : T = e =df {x, var} :
(x ∈ var) ∧ (x0 = < value(e) > ·x) ∧
(var0 = {x} £ ∪ {(x, < T > ·var(x))}) ∨ (WD(e) ∧ (type(e) ¹ T )) ` / var ∧ (x0 = < value(e) >) ∧ x∈ (var0 = var ∪ {(x, < T >)})
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Commands
9
end x =df
length(var(x)) = 1 ∧ var0 = {x} £ var
∨ {var, x} : (x ∈ var) ` length(var(x)) > 1 ∧ x0 = tail(x) ∧
var0 = {x} £ var ∪ {(x, tail(var(x)))} where {x} £ var represents the set var after removal of variable x. Let C be a class with {a1 , ..., an } as its attributes. The execution of C.N ew(x) yields a new instance of type C. C.N ew(x) =df {var, x, x.a1 , .., x.an } : ((x ∈ var) ∧ (x0 = < x > ·x) ∧ ∀i • x.a0i =< value(Initial(C.ai )) > ·x.ai ∧ (var0 = {x} £ var ∪ {(x, < C > ·var(x))}) C ∈ cname ` ∨ x∈ 0 0 / var ∧ (x = < x >) ∧ ∀i • x.ai =< value(Initial(C.ai )) > ∧ (var0 = var ∪ {(x, < C >)})) Let vale, rese and valrese be lists of expressions. The program le.m(vale, rese, valrese) assigns the values of the actual parameters vale and valrese to the formal value and value-result parameters of the method m of object o, and then executes the body of m. After it terminates, the values of the result and value-result parameters of m are passed back to the actual parameters rese and valrese. le.m(vale, rese, valrese) =df (WD(le) ∧ type(le) ∈ cname ∧ m ∈ op(type(le)) ⇒
∃N • (type(le) = N ∧ var self : N = le, x : T1 = vale, y : T2 = valrese, z : T3 = rese ;
N.m ; if type(valrese) ∈ cname ∧ type(rese) ∈ cname → skip type(valrese) ∈ / cname ∧ type(rese) ∈ cname → rese = y type(valrese) ∈ cname ∧ type(rese) ∈ / cname → valrese = z type(valrese) ∈ / cname ∧ type(rese) ∈ / cname → rese, valrese = y, z ; fi ; end self, x, y, z
where x, y and z are the value, result and value-result parameters of the method m of class type(le) with primitive types T1 , T2 and T3 respectively, and N.m stands for the design associated with the method m of class N .
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Class Declarations
5
10
Class Declarations
This section deals with class declarations. A single class declaration is treated in the first subsection. The second subsection formalises the whole class declaration section by figuring out a family of recursive equations to explore mutual dependency among methods.
5.1
Class declaration
A class declaration cdecl has the following form class N
extends M
pri u1 : U1 = d1 , ..., ui : Ui = di pro v1 : V1 = e1 , ..., vj : Vj = ej pub w1 : W1 = f1 , ..., wk : Wk = fk meth m1 =df val x1,1 : T 1, 1 , res y 1,1 : T 1,2 , valres z 1, 3 : T 1,3 • c1 , ..... ml =df val xl,1 : T l,1 , res y l,2 : T l,2 , valres z l,3 : T l,3 • cl end where • N is the name of this newly declared class. and M is its direct superclass. • The section pri u1 : U1 = d1 , ..., ui : Ui = di defines u1 , ..., ui as the private attributes of class N , while U1 , ..., Ui and d1 , ..., di represent their types and initial values respectively. This section is optional as not every class has to have private attributes. • The section pro v1 : V1 = e1 , ..., vj : Vj = ej introduces the protected attributes of N . This section is also optional. • The section pub w1 : W1 = f1 , ..., wk : Vk = fk gives the public attributes of N . This section is again optional, • m1 , ... , ml are methods defined in N , where xi,1 : T i,1 , y i,2 : Ti,2 , z i,3 : Ti,3 and ci represent the value, result and value-result parameters and the body of the method mi . This method section is also optional. The class declaration cdecl is well-defined when it meets the following conditions 1. N has not been declared before. 2. N and M are distinct.
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Class Declarations
11
3. Its attribute names are distinct 4. The initial values of the attributes match their corresponding types. 5. The method names are distinct. 6. The parameters of every method are distinct. which can be formalised by WD(cdecl) =df N ∈ / cname ∧ N 6= M ∧ distinct(< u1 , .., ui > · < v1 , ..., vj > · < w1 , ..., wk > · < m1 , .., ml >) ∧ ∀n : 1..i • type(dn ) = Un ∧ ∀n : 1..j • type(en ) = Vn ∧ ∀n : 1..k • type(fn ) = Wn ∧ ! Ã distinct(xn,1 · y n,2 · z n,3 ) ∧ length(xn.1 ) = length(T n.1 ) ∧ ∀n : 1..l • length(y n,2 ) = length(T n,2 ) ∧ length(z n,3 ) = length(T n,3 ) We shall deal with the well-definedness the method definitions in the end of class declaration section. The class declaration cdecl adds the structural information of class N to the state of the followup program, and this role is captured by the design cdecl =df {cname, superclass, priattr, protattr, pubattr} : cname0 = cname ∪ {N } ∧ superclass0 = superclass ⊕ {N 7→ M } ∧ priattr0 = priattr ⊕ {N 7→ {< u : U , d >, ... , < u : U , d >} ∧ 1 1 1 i i i protattr0 = protattr ⊕ {N 7→ {< v1 : V1 , e1 >, ... < vj : Vj , ej >} ∧ WD(cdcl) ` pubattr0 = pubattr ⊕ {N 7→ {< w1 : W1 , f1 >, ... < wk : Wk , fk >} ∧ (m1 7→ (< x1,1 : T1,1 , y 1,2 : T1,2 , z 1.3 : T1,3 >, c1 ), 0 = op ⊕ {N 7→ ...... op ml 7→ (< xl,1 : Tl,1 , y l.2 : Tl,2 , z l,3 : Tl,3 >, cl ) where the logical variables priattr, protattr and pubattr are introduced to record the declared attributes of N , from which the state component attr can later be constructed. Similarly, the dynamic behaviour of the methods can not be formalised before the dependency relation among classes is specified. At moment, the logic variable op(N ) binds each method mi to code ci rather than its definition which will be calculated in the end of the declaration section.
5.2
Definition of a declaration section
A class declaration section comprises a sequence of class declarations, and it is well-defined if the following conditions are met:
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Class Declarations
12
1. All class names used in the variable and parameter declarations are defined in the section. V WD1 =df x:T ∈S T ∈ cname ∧ T is primitive where S denotes the set of variables, attributes and parameters present in the declaration section. S S =df var ∪ C∈cname π1 (range(op(C)) ∪ pricattr(C) ∪ protattr(C) ∪ pubattr(C)) 2. The function superclass does NOT induce circularity. WD2 =df superclass+ ∩ Id = ∅ where we abuse the notation by treating superclass as a binary relation, and define superclass+ as the transitive closure of superclass. 3. No attribute of a class can be redefined in its subclass. WD3 =df ∀N, M • (N, M ) ∈ superclass+ ⇒ attrname(N ) ∩ attrname(M ) = ∅ where attrname(N ) comprises all the attributes defined in class N . attrname(N ) =df {x | ∃T, d • < x : T, d >∈ priattr(N ) ∪ protattr(N ) ∪ pubattr(N )} 4. No method is allowed to redefine its signature in its subclass. WD4 =df ∀ N, M : cname, ∀ m : dom(op(N )) ∩ dom(op(M )• (N, M ) ∈ superclass+ ⇒ π1 (op(N )(m)) = π1 (op(M )(m)) Let cdecls be a class declaration section, and P be a command, the meaning of a program (cdecls • P ) is defined as the composition of the meaning of class declarations cdecls (defined in Section 5.2) and the design init and the meaning of command P . cdecls • P =df (cdecls ; init ; P ) where the design init performs the following tasks 1. to check the well-definedness of the declaration section, 2. to decide the values of attr and visibleattr from those of priattr, protattr and pubattr. 3. to define the meaning of every method body c
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Class Declarations
13
init =df {visibleattr, attr, op} : (WD1 ∧ WD2 ∧ WD3 ∧ WD4) ` S visibleattr0 = N ∈cname {N.a | ∃T, c • < a : T, d >∈ pubattr(N )} ∧ ∀N : cname • S attr0 (N ) = {priattr(M) ∪ protattr(M ) ∪ pubattr(M ) | N ≤ M } ∧ op0 (N ) = {(m 7→ (< x : T , y : T , z : T >, Ψ(N.m))) | 1 2 3 (∃c • {m 7→ (< x : T, y : T2 , z : T3 >, c)} ∈ op(M ) ∧ N ≤ M }
where the family of designs Ψ(N.m) is defined in sequel.
5.3
Formalisation of methods
The family of the designs Ψ(N.m) is defined by a set of recursive equations, which contains for each class N ∈ cname and every method m ∈ {op(M ) | N ≤ M } an equation Ψ(N.m) = FN.m (Ψ) where F is constructed by the following rules: Case (1): m is not defined in N , but in a superclass of N , that is m ∈ / op(N ) ∧ m ∈ S {op(M ) | N ≤ M }. The defining equation for such case is simply FN.m (Ψ) =df Ψ(M.m)
where superclass(N ) = M .
Case (2): m is a method defined in class N . In this case, the behaviour of the method N.m is captured by its body and the environment in which it is executed FN.m (Ψ) =df
set(N ); φN (body(N.m)); reset
where the design set(N ) finds out all attributes visible to class N , whereas reset does it for the main program. set(N ) =df {visibattr} : {N.a | ∃T, c • < a : T, c >∈ priatttr(N )} ∪ S true ` visibattr0 = N ≤M {M.a | ∃T, d • < a : T, d >∈ protattr(M )} ∪ S M ∈cname {M.a | ∃T, d • < a : T, d >∈ pubattr(M )} reset =df {visibattr} : S true ` visibattr0 = M ∈cname {M.a | ∃T, d• < a : T, d >∈ pubattr(M )} The function φN renames the attributes and methods of class N in the code body(N.m) by
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
Conclusion
14
adding object reference self . φN (skip) =df φN (chaos) =df
chaos
φN (p1 ; p2 ) =df
φN (p1 ); set; φN (p2 )
φN (P1 ¢ b ¤ P2 ) =df φN (P1 u P2 ) =df φN (b ∗ p) =df φN (var x : T = e) =df φN (end x) =df
φN (p1 ) ¢ φN (b) ¤ φN (p2 ) φN (p1 ) u φN (p2 ) φN (b) ∗ (φN (p); set) var x : T = φN (e) end x
φN (C.N ew(x)) =df
C.N ew(φN (x))
φN (l := e) =df
φN (l) := φN (e)
φN (le.m(vale, ˆ rese, valrese)) =df φN (m(vale, ˆ rese, valrese)) =df φN (self ) =df φN (x) =df
6
skip
φN (le).m(φ(vale), ˆ φ(valrese), φ(rese)) self .m(φ(vale), ˆ φ(valrese), φ(rese)) self ( self .x x
φN (le.x) =df
φN (le).x
φN (null) =df
null
φN (e is C) =df
φN (e) is C
φN ((C)e) =df
(C)φN (e)
φN (f (e)) =df
f (φN (e))
x∈
S N ≤M
attrname(M )
otherwise
Conclusion
Our approach has mostly been influenced by the development of the design calculus based on the standard predicate logic. The difference is that states are encoded as a mapping from variables to sequences of values in coping with nested declaration of variables. The approach also permits object names as values and mutually dependent methods. However, we have not dealt with concurrency in object technology. This remains the subject of further work. The combination of formal techniques and object-orientation has achieved significant advances
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
References
15
in both fields. Future challenges for formal methods in object technology include a formal treatment of patterns [13]. In addition, tool support for formal object-oriented methods is an area of considerable significance for further industrial take-up of these methods.
References [1] M. Abadi and L. Cardelli. A Theory of Objects. Springer-Verlag, (1996). [2] M. Abadi and K.R.M. Leino. A logic of object-oriented programs. Lecture Notes in Computer Science 1214, 682–696, Springer, (1997) [3] P. America. Designing an object-oriented programming language with behavioural subtyping. Lecture Notes in Computer Science 489, 60–90, (1991). [4] R.J.R. Back and M.J. Butler. Exploring summation and product operators in the refinement calculus. Lecture Notes in Computer Science 947, (1995). [5] D. Carrington, et al. Object-Z: an object-oriented extension to Z. North-Holland, (1989). [6] A. Cavalcanti and D. Naumann. A Weakest Precondition Semantics for an Object-Oriented Language of Refinement. Lecture Notes in Computer Science 1708, 1439–1460, (1998) [7] D. Coleman, et al. Introducing objectcharts or how to use statecharts in object-oriented design. IEEE Transactions of Software Engineering, 18(1), (1992) [8] D. Coleman, et al. Object-oriented development: the FUSION method. Prentice Hall Object-oriented Series, (1994). [9] S. Cook and J. Daniels. Designing Object Systems: Object-Oriented Modelling with Syntropy. Prentice-Hall, (1994).
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
References
16
[10] J. Dong, R. Duke and G. Rose. An object-oriented approach to the semantics of programming languages. In G. Gupta (ed): 17th Annual Computer Science Conference (ACSC’17), 765–775, (1994). [11] E.H. Durr, et al. The role of V DM ++ in the development of a real-time tracking and tracing system. In Proceedings of FME’93, Lecture Notes in Computer Science. Springer-Verlag, (1993). [12] R.W. Floyd. Assigning meanings to programs. Proceedings of Symposia in Applied Mathematics, Vol 19: 19–32, (1967) [13] E. Gamma, et al. Design patterns. Addison-Wesley, (1995). [14] C.A.R. Hoare and He Jifeng. Unifying Theories of Programming. Prentice Hall, (1998) [15] I. Houston. Formal specification of the OMG core object model. Technical Report, IBM UK, Hursely Park, (1994). [16] K. Lano and H. Haughton. Reasoning and refinement in object-oriented specification language. Lecture Notes in Computer Science 615, Springer-Verlag, (1992). [17] A. Mikhajlova and E. Sekerinski. Class refinement and interface refinement in object-oriented programming. Proceedings of FME’97, Springer, (1997). [18] D.A. Naumann. Predicate transformer semantics of an Oberon-like language. In E.-R. Olderog (ed) Programming Concepts, Methods and Calculi, 460–480, (1994). [19] K. Rustan and M. Leino. Recursive object types in a logic of object-oriented programming. Lecture Notes in Computer Science 1381, (1998). [20] E. Sekerinski.
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau
References
17
A type-theoretical basis for an object-oriented refinement calculus. Proceedings of Formal Methods and Object Technology, Springer-Verlag, (1996) [21] M. Spivey. The Z notation: a reference manual. Prentice Hall, 2nd edition, (1992). [22] A. Tarski. A lattice-theoretical fixpoint theorem and its applications. Pacific Journal of Mathematics, Vol 5: 285–309, (1955).
Report No. 280, May, 2003
UNU/IIST, P.O. Box 3058, Macau