overloading and inheritance

12
Overloading and Inheritance Davide Ancona , Sophia Drossopoulou , Elena Zucca DISI, University of Genova, Department of Computing, Imperial College E-mail: Abstract Overloading allows several function definitions for the same name, distinguished primarily through different argu- ment types; it is typically resolved at compile-time. Inher- itance allows subclasses to define more special versions of the same function; it is typically resolved at run-time. Modern object-oriented languages incorporate both fea- tures, usually in a type-safe manner. However, the combina- tion of these features sometimes turns out to have surpris- ing, and even counterintuitive, effects. We discuss why we consider these effects inappropriate, and suggest alternatives. We explore the design space by isolating the main issues involved and analyzing their in- terplay and suggest a formal framework describing static overloading resolution and dynamic function selection, ab- stracting from other language features. We believe that our framework clarifies the thought process going on at lan- guage design level. We introduce a notion of soundness and completeness of an overloading resolution policy w.r.t. the underlying dy- namic semantics, and a way of comparing the flexibility of different resolution policies. We apply these concepts to some non-trivial issues raised in concrete languages. We also argue that the semantics of overloading and in- heritance is “clean” only if it can be understood through a copy semantics, whereby programs are transformed to equivalent programs without subclasses, and the effect of inheritance is obtained through copying. 1 Introduction Overloading allows for functions that execute different code for arguments of different types, and is supported by many programming languages [17, 15]. It is also called ad hoc polymorphism, in contrast to parametric polymor- phism, as, e.g., in [14], which allows for functions whose code works uniformly on arguments of different types [5]. Earlier languages offer only a form of overloading where the appropriate body for a function call is selected at com- pile time, that is, overloading resolution is static (early or static binding). This form of overloading can be reduced to a syntactic abbreviation. In languages where types may be computed at run-time, indeed, the appropriate body for a function can be selected depending on the dynamic type of the arguments; hence we have late or dynamic binding. This happens typically with inheritance in object-oriented languages; usually run-time selection is adopted only for the receiver ( i.e., the first, im- plicit, parameter) of a method call. The same policy can also be applied to all, or some of, function arguments, as, e.g., in multimethods [12, 7]. Foundations of languages sup- porting run-time selection are investigated in [6]. In many widely-used languages, e.g., Java [4] and C++ [15], a combination of the two mechanisms is supported, and the terms “overloading” and “inheritance” are used to denote the static and the dynamic selection, respectively. This is the sense in which we use these terms in our paper. In such languages, a class can both overload methods, that is, have methods with the same name but different ar- gument types, and override methods inherited from parent classes. Hence, given a method call, the choice of the code to be executed requires two steps: first a static selection, performed on the basis of the static types of the receiver and the arguments, then a dynamic selection, performed on the basis of the dynamic type of the receiver and some in- formation, which we call (method) descriptor, stored with the call at compile-time. Obviously, the primary aim of a language design needs to be type-safety. Achieving it in the context of both in- heritance and overloading is non-trivial [8, 13]. However, there are further concerns, to do with how permissive and intuitive the ensuing semantics is. In previous work [3] we discussed cases where Java overloading resolution is too re- strictive, and suggested alternatives. In this paper we provide a more rigorous foundation to our earlier observations. We define a framework for- malizing the mechanisms of static and run-time selection, and their interaction, abstracting from orthogonal features. Within this framework, we introduce two notions evaluating

Upload: unige-it1

Post on 18-Nov-2023

0 views

Category:

Documents


0 download

TRANSCRIPT

Overloading and Inheritance

Davide Ancona1, Sophia Drossopoulou2 , Elena Zucca11 DISI, University of Genova, 2 Department of Computing, Imperial CollegeE-mail: fzu a; davideg�disi:unige:it sd�do :i :a :uk

Abstract

Overloading allows several function definitions for thesame name, distinguished primarily through different argu-ment types; it is typically resolved at compile-time. Inher-itance allows subclasses to define more special versions ofthe same function; it is typically resolved at run-time.

Modern object-oriented languages incorporate both fea-tures, usually in a type-safe manner. However, the combina-tion of these features sometimes turns out to have surpris-ing, and even counterintuitive, effects.

We discuss why we consider these effects inappropriate,and suggest alternatives. We explore the design space byisolating the main issues involved and analyzing their in-terplay and suggest a formal framework describing staticoverloading resolution and dynamic function selection, ab-stracting from other language features. We believe that ourframework clarifies the thought process going on at lan-guage design level.

We introduce a notion ofsoundnessand completenessof an overloading resolution policy w.r.t. the underlying dy-namic semantics, and a way of comparing theflexibilityof different resolution policies. We apply these concepts tosome non-trivial issues raised in concrete languages.

We also argue that the semantics of overloading and in-heritance is “clean” only if it can be understood througha copy semantics, whereby programs are transformed toequivalent programs without subclasses, and the effect ofinheritance is obtained through copying.

1 Introduction

Overloadingallows for functions that execute differentcode for arguments of different types, and is supported bymany programming languages [17, 15]. It is also calledad hoc polymorphism, in contrast toparametric polymor-phism, as,e.g., in [14], which allows for functions whosecode works uniformly on arguments of different types [5].Earlier languages offer only a form of overloading where

the appropriate body for a function call is selected at com-pile time, that is,overloading resolutionis static (early orstaticbinding). This form of overloading can be reduced toa syntactic abbreviation.

In languages where types may be computed at run-time,indeed, the appropriate body for a function can be selecteddepending on thedynamic typeof the arguments; hence wehavelate or dynamic binding. This happens typically withinheritancein object-oriented languages; usually run-timeselection is adopted only for the receiver (i.e., the first, im-plicit, parameter) of a method call. The same policy canalso be applied to all, or some of, function arguments, as,e.g., in multimethods[12, 7]. Foundations of languages sup-porting run-time selection are investigated in [6].

In many widely-used languages,e.g., Java [4] and C++[15], a combination of the two mechanisms is supported,and the terms “overloading” and “inheritance” are used todenote the static and the dynamic selection, respectively.This is the sense in which we use these terms in our paper.

In such languages, a class can bothoverloadmethods,that is, have methods with the same name but different ar-gument types, andoverridemethods inherited from parentclasses. Hence, given a method call, the choice of the codeto be executed requires two steps: first a static selection,performed on the basis of the static types of the receiverand the arguments, then a dynamic selection, performed onthe basis of the dynamic type of the receiver and some in-formation, which we call(method) descriptor, stored withthe call at compile-time.

Obviously, the primary aim of a language design needsto be type-safety. Achieving it in the context of both in-heritance and overloading is non-trivial [8, 13]. However,there are further concerns, to do with how permissive andintuitive the ensuing semantics is. In previous work [3] wediscussed cases where Java overloading resolution is too re-strictive, and suggested alternatives.

In this paper we provide a more rigorous foundationto our earlier observations. We define a framework for-malizing the mechanisms of static and run-time selection,and their interaction, abstracting from orthogonal features.Within this framework, we introduce two notions evaluating

overloading resolution policies.The first notion issoundnessandcompleteness w.r.t.the

underlying dynamic semantics. Soundness requires all de-scriptors which are not distinguishable by overloading reso-lution not to be distinguishable when used for method selec-tion; completeness requires the converse. Soundness guar-antees determinism; completeness guarantees that overload-ing resolution is not more discriminating than necessary.Completeness is not satisfied by the 1996 Java version [11]nor by C++ [15].

The second notion isflexibility: an overloading resolu-tion policy is more flexible than another iff it gives the samemeaning to all method calls which are unambiguous for thelatter. We describe alternatives which are sound and com-plete, and strictly more flexible than Java.

A plausible expectation is that inheritance should be ex-plainable through acopy semantics, whereby any programshould be transformable into an equivalent program withoutinheritance, inherited methods should be copied into thebodies of the transformed subclasses. Indeed, similar mech-anisms for object based calculi are used in [1, 10]. Interest-ingly, it turned out that some approaches,e.g., the 1996 Javaversion, do not have a natural copy semantics, and the ap-proach that has the best properties in terms of soundnessand completeness has the simplest copy semantics.

In the next section we explore the above issues throughexamples. In section 3 we give a formal framework foroverloading and inheritance. In section 4 we apply theframework to analyze the policy of Java, describe two al-ternatives and demonstrate their properties. We also showan extension allowing multiple inheritance and compare itwith the C++ approach. In section 6 we draw conclusionsand describe further work.

2 Examples

As outlined earlier, a method call has an associatedstaticoverloading resolution, and a dynamicmethod selec-tion step. Overloading resolution consists of two phases:first, determine the associated set ofcandidate methods,i.e., methods which could correspond to the call; then, se-lect from this set the method (or, in general, the methods;as shown later, sometimes more than one method can beselected) whichfits best, and store its descriptor with themethod call. Based on the dynamic class of the receiver andthe stored method descriptor, method selection finds the ap-propriate method body, which needs not be the same as thatchosen at compile-time.

Unless explicitly stated, in all following examplesB0is assumed to be a subclass ofA0 and the set of candi-date methods is determined according to the Java rule (see15.11.2.1 in [11] or 15.12.2.1 in [4]): for a call of a methodm whose receiver and actual arguments have static types

andt1:::tn, candidates are all methods either declared orinherited1 by with namem and parameter typest01:::t0n,wheret0i supertype ofti, for all 1 � i � n.

2.1 Simple cases of overloading resolution

We illustrate first the simpler cases of overloading reso-lution. Consider the following example.

class A { int m(A’ x) { return 1; } }class B extends A { int m(B’ x) { return 2; } }

Consider method callb:m(b0) whereb, b0 are expressions oftypeB, B0, respectively. There are two candidate methods,since both could be correctly associated to the given call,but there is no doubt that the method declared inB “fitsbetter” than that declared inA. Java terminology says thatthe method fromB is more specificthan that fromA.

In the example above, both the argument type of themore specific method and the class where it is declared area subtype of those of the other. The choice between can-didate methods is also straightforward when either they aredeclared in the same class and one has more specific argu-ment types or both have the same argument types but one isdeclared in an heir class (hence overrides the other).

Finally, the following shows that overloading resolutionmay flag static errors, when there is no “reasonable” way tochoose between candidate methods.

class C { int m(A’ x, B’ y) { return 1; }int m(B’ x, A’ y) { return 2; } }

In this case, in the call :m(b0; b0), where andb0 have typesC andB0, respectively, neither method fits better, hence thisis a static error, and the call is said to beambiguous.

We now turn to examples where the choice as to whichmethod fits better is less obvious.

2.2 Resolution too restrictive – possibly

The following example demonstrates that languages maybe too restrictive in overloading resolution.

Example 1class A { int m(B’ x) { return 1; } }class B extends A { int m(A’ x) { return 2; } }class C extends B { }

In this case, there is contravariance between inheritance andargument subtyping, hence the meaning of the call :m(b0)is debatable. In C++ it resolves to the method in classB (seelater). In Java the call is ambiguous, since a method is morespecific than another only if it has more specific argumenttypesand is declared in a subclass/subinterface.1In Java inherited means not overridden (see 8.4.6 in [11, 4]).

People are puzzled when first confronted with this be-havior in Java. There are counter-arguments both on themethodological and the descriptive level.

On the methodological level, the Java approach has theimplication (bad for modular software development) thatclients of a class need to know not only which methodsare provided by it, but also from which class each methodhas been inherited. For instance, the specification of classCstates that it has two methodsint m(B0 x) andint m(A0 x);but this information is insufficient to predict the effect ofthecall :m(b0).

On the descriptive level, this rule does not support a sim-ple copy semantics (in the sense explained below).

We now show four different approaches where :m(b0) isnot ambiguous: the former two approaches adopt the Javarule for candidate methods, but are based on two alterna-tive rules for selecting the method that fits best, whereas thelatter two approaches are based on different rules for deter-mining the set of candidates.

First Alternative: arguments-only rule A better al-ternative would consider the argument types only, and se-lect for :m(b0) the method returning 1. This solution cor-responds to a cleaner view both on the methodological andthe descriptive level.

With this approach, indeed, inheritance is explainable asa mechanism for code sharing without duplication. It canbe seen as a linguistic mechanism allowing to get for freethe same effect as if one duplicated “by hand” in the heir allparent’s methods (unless overridden).

With copy semantics our example is transformed to:

class A { int m(B’ x) { return 1; } }class B extends A { int m(A’ x) { return 2; }

int m(B’ x) { return 1; } }class C extends B { int m(A’ x) { return 2; }

int m(B’ x) { return 1; } }

In the above, the call :m(b0) would be unambiguous andwould return 1. In Sect.4.1 (Prop.4), we formally expressthis fact by showing that the arguments-only rule is strictlymore flexible than the Java (componentwise) rule.

Second Alternative: subclasses first rule Anotherpossible solution would be for the method call :m(b0) toreturn 2, selecting from the set of candidates the methoddeclared in the first superclass.

This alternative can be explained in terms of a differentcopy semantics: we copy each method of the parent in theheir, unless the heir contains a method with the same nameand argument types which are supertypes of those of theparent’s method. For instance, example 1 would be trans-formed as follows.

class A { int m(B’ x) { return 1; } }class B extends A { int m(A’ x) { return 2; } }class C extends B { int m(A’ x) { return 2; } }

This solution has the methodological advantage of bringingstatic overloading resolution in line with dynamic methodselection, which selects thefirst appropriatemethod.

Third Alternative: C++ rule C++ differs from thetwo previously described approaches in the definition of thecandidate methods. For a call of a methodm whose re-ceiver and actual arguments have static types andt1:::tn,respectively, candidates are all methods which have namemand parameters typest01:::t0n, with t0i supertype ofti, for all1 � i � n, and which are declared (or imported viausingclauses) in the first superclass of which hassomemethodnamedm. According to this rule, the method defined inBis the only candidate for the call :m(b0). More details canbe found in appendix B.

The C++ rule can be explained in terms of a differentcopy semantics: We copy each method of the parent in theheir, unless the heir contains a method with the same name;methods of classes mentioned inusingclauses are copied inany case. Examples are given in appendix B.

Fourth Alternative: Contravariant methods If weallow overriding of contravariant methods, then the methoddeclared inB overrides that declared inA; as a consequence,if overridden methods are not candidates as happens in Java,then again the method defined inB is the only candidate forthe call :m(b0).

In this case the copy semantics is obtained by duplicatingparent’s methods (unless overridden) in the heir, as happensfor the first alternative.

class A { int m(B’ x) { return 1; } }class B extends A { int m(A’ x) { return 2; } }class C extends B { int m(A’ x) { return 2; } }

2.3 Resolution unduly restrictive – undoubtedly

In the following case, overloading resolution is undulyrestrictive, because it flags an ambiguous call where, in fact,in any execution there is exactly one matching method body.

In a language which supportsabstract methods, like,e.g., Java, it is possible for a class/interface to inherit morethan one method with the same argument and return types(see [4] 8.4.6.4). This leads to a particular case of ambigu-ity, illustrated below.

Example 2interface I1 { int m(); }interface I2 { int m(); }interface I3 extends I1, I2 { }

Consider the calli:m() with i of type I. Following theJava rule based on componentwise ordering, from chap-ter 15.11.2.2 in [11], this call should be ambiguous (eventhough different Java compilers have different, and some-time obscure, behavior on this and similar examples). Thesecond alternative gives the same result as well.

In our view, this choice is unduly restrictive for evenstronger reasons than those from 2.2: Any class imple-menting interfaceI will either declare or inheritexactly onemethodint m(); thus, execution ofi:m() will always findexactly one method body. Thus, overloading resolution isunduly discriminating. In Sect.4.2 (Prop.6) we formalizethis by proving that the Java rule is notcomplete, that is, itmakes ambiguous calls for which the ambiguity is not se-mantically relevant. Overloading resolution in C++ has thesame drawback (a similar example to the above can be con-structed using abstract methods).

On the contrary, the first alternative makes the call un-ambiguous. Both the Java rule and the second alternativecan be changed so that the call becomes unambiguous, bytreating abstract methods specially (see Def.8 in Sect.4.2).For Java this corresponds to the overloading rule given inthe revised Java specification ([4] 15.12.2.2).

2.4 Overloading and multiple inheritance

We now consider the case where classes may inheritmore than onenon-abstractmethod with the same argu-ment and return types. This is possible in languages withmultiple inheritance2, as,e.g., C++.

Let us consider first the case in which a class inheritsmore than onenon virtual3 method with the same argumentand return types, as in the following example4.

Example 3class C { int m() { return 1; } }class C1 : virtual C { int m() { return 2; } }class C2 : virtual C { int m() { return 3; } }class C3 : virtual C1, virtual C2 { }

Here, the the call 3:m(), with 3 of typeC3 shouldbe am-biguous.5 However, there is no reason to forbid the declara-tion of C3 – calls of other methods with receiver 3 couldbe valid, and subclasses ofC3 may define their own methodint m(). On the other hand, if a class inherits differentvir-tual methods which do not override each other (asC3 in theexample above if all methods are virtual), then the class isill-formed, since there would be no way to prevent run-timeambiguities by type-checking method calls: for instance,2There, selection among methods inherited from different parent classes is calledconflict rather than overloading resolution, but obviouslythe problem is the same.3That is, a method for which binding is static.4Notice that we are using virtual inheritance; more in Sect.4.3.5As a consequence, the arguments-only rule is no longer sound; this correspondsto the fact that there is no simple copy semantics of multipleinheritance.

the call :m(), where has static classC, would cause arun-time ambiguity on a receiver with dynamic typeC3.

In Sect.4.3 we suggest a formal overloading resolutionrule which takes these problems into account, and we proveits soundness and completeness.

3 Language and Overloading frameworks

We develop an abstract framework distilling the essentialcomponents from overloading and inheritance as in severalprogramming languages. We consider languages with over-loading, inheritance, classes, abstract classes, interfaces,where classes are types, and subclasses are subtypes.

For any programming language we assume an associatedset of well-formed programsP. For anyp2P, we assume as-sociated sets of method namesMp, classesCp, interfacesIp,and abstract classesACp with ACp � Cp. The sets of classand interface names must be disjoint; their union representspossible typesTp and is ordered by a subtype relationvp.Note that, even though both have no instances (differentlyfrom non-abstract classes), abstract classes and interfacesare separate entities, since the former are involved in run-time method selection.

The set of all possible method bodies is described byBp.Method calls involve two processes: At compile time,

the method call is enriched by additional information,which we call descriptor, formalized as the setDs r. Atrun-time, the method body is selected based on the dy-namic class of the receiver, the name of the method, andthe method descriptor. This is formalized by the functionMSelp:Cp�Mp�Ds rp �! Bp [ fnoneg, which returnsa method body, ornone if no body is found.6

The compile-time calculation of descriptors involves twostages: In the first stage, the candidate methods are col-lected, based on the static type of the receiver, the methodname, and the static types of the arguments,i.e., the functionCndMsp:Tp�Mp� Tp� �! P(Ds rp)7 is applied. In thesecond stage, the maximally specific candidates (accordingto a more specificrelation� p) are collected. The call isun-ambiguousif this set contains equivalent descriptors (inthe sense of�p) only.

The predicate:p, defined onBp � (CpnACp) � Ds rp,determines whether a bodyb2Bp satisfies the descriptord 2 Ds rp when executed by objects of class 2 CpnACp(dynamic class of the receiver).

Since, as already noted, overloading resolution consistsof two distinct phases, we distinguish theprogramming lan-guage framework, as in Def.1, which may underly differentmore specific relations, thus giving differentoverloadingframeworks, as in Def.2.6MSelp is defined on all classes, therefore on abstract classes, in particular. Thisallows a neat, recursive definition ofMSelp in the particular frameworks introducedin Sect. 4.7P(A) denotes the powerset of setA.

Definition 1 We call a tupleL = (P;M;C;AC; I;v ;Ds r;CndMs ;B;MSel ; :) a language frameworkiff, for anyp2P: � Mp is a set,� Cp andIp are disjoint sets,ACp � Cp,� vp is a subtype relation onTp, whereTp = Ip [ Cp,� Ds rp is a set,� CndMsp:Tp�Mp� Tp� �! P(Ds rp) is a totalfunction,� MSel p:Cp�Mp�Ds rp �! Bp [ fnoneg is a totalfunction,� :p � Bp� (CpnACp)�Ds rp.

From now on,L denotes given language framework, withL = (P;M;C;AC; I;v ;Ds r;CndMs ;B;MSel ; : ).Definition 2 We call a pairO = hL;�i an overloadingframeworkiff:� L is a language framework,� �p is a relation onDs rp,� setMaxMs�p(t0;m;�t) =f d j d2CM; and d02CM; d0 �pd =) d �pd0 g;

for anyt0;m;�t, and whereCM = CndMsp(t0;m;�t),then�p is a pre-order8 onMaxMs�p(t0;m;�t),for anyt0;m;�t.

We callL the underlyinglanguage framework ofO, andthe relation� p a more specific relation. In appendix A weapply the above definition to the first example in 2.1. Insection 4 we define different frameworks corresponding toJava overloading resolution and alternatives, and a frame-work including multiple inheritance.� p is a pre-order only on the setsMaxMs�p(t0;m;�t),and not onDs rp. The reason for that is that the requirementfor � p to be pre-order onDs rp is not always met in pro-gramming languages (see Def.8 and the counter-example inApp.C).

From now on,O = hL;�i denotes some given over-loading framework.

Definition 3 We define the relation��p on Ds rp, and the

predicateUnAmb�p onTp�Mp� Tp� as follows:� d0 ��p d iff d0 �pd andd �pd0,� UnAmb�p(t0;m;�t) iff8d; d02MaxMs�p(t0;m;�t) : d ��p d0.8 i.e.„ transitive and reflexive, but not necessarily anti-symmetric.

��p is an equivalence relation onMaxMs�p(t0;m;�t), since�p is a pre-order on that set. Also, a call is ambiguous onlyif there are non comparable maximally specific candidates,since the following lemma trivially holds.

Lemma 1 For all p, t0;m;�t, d; d0 :d; d0 2 MaxMs�p(t0;m;�t), d �pd0 =) d ��p d0.3.1 Properties of frameworks

In order for an overloading framework to be part of asafe type system, we require that method selection startingfrom a (non-abstract) class and based on the descriptord of any candidate method provides a method body (i.e.,MSelp( ;m; d) 6= none, which guarantees progress), andthat this method body when executed by objects of class satisfies the given descriptor (i.e., MSelp( ;m; d):ph ; di,which guarantees type preservation).

Definition 4 L is type safeiff, for all t0;m;�t, 2CpnACp :d2CndMsp(t0;m;�t), vp t0 =)� MSelp( ;m; d) 6= none,� MSelp( ;m; d):ph ; di.As we argued in section 2.2, there are further requirements:Overloading resolution should make as many distinctions ascan be perceived through dynamic method selection, but nomore. Thus, we define the notions ofsoundandcompleteoverloading resolution.

Definition 5 For anyp2P, t02Tp, we define thesemanticequivalence�t0p onDs rp as� d �t0p d0 iff8 vp t0 : MSelp( ;d) = MSelp( ; d0).Then, the more specific relation� is� soundw.r.t.L iff 8p2P; d; d02MaxMs�p(t0;m;�t) :d ��p d0 =) d �t0p d0,� completew.r.t.L iff 8p2P; d; d02MaxMs�p(t0;m;�t) :d �t0p d0 =) d ��p d0.Completeness is a strong language design criterion. It re-quires any compile-time ambiguous call to be sensitive tothe choice of descriptor from the set of maximally specificdescriptors. Java overloading as in the 1996 version is notcomplete, as illustrated in example 2, and formally arguedin Prop. 6.

Lemma 2 � is sound w.r.t.L if it is a partial order9 onMaxMs�p(t0;m;�t), for anyt0;m;�t.A more specific relation is less flexible than another more

specific relation if each unambiguous callw.r.t. the first isunambiguousw.r.t. the latter, and gives the same result:

Definition 6 Let hL;�1i and hL;�2i be overloadingframeworks s.t.� 1 and� 2 are sound w.r.t.L. We saythat�1 is less flexiblethan�2 w.r.t.L iff, for all p2P, andfor all t0;m;�t:UnAmb�1p(t0;m;�t) =)� UnAmb�2p(t0;m;�t)�8d2MaxMs�1p(t0;m;�t); d02MaxMs�2p(t0;m;�t): d�t0p d0.Note that, by virtue of the soundness hypothesis, in the sec-ond consequence universal quantifiers can be equivalentlyreplaced by existential quantifiers.

4 Examples of overloading frameworks

We now consider the issues illustrated in section 2 interms of the formalization introduced in the previous sec-tion. We first develop a language frameworkLs which cor-responds to a Java-like language with single inheritance andnon-abstract classes only. On top ofLs we define threeoverloading frameworks,Os;j , Os;a1 andOs;a2 which cor-respond to the Java rule and the two alternative rules infor-mally introduced in section 2. We show thatOs;j , Os;a1andOs;a2 are sound and complete, butOs;j is strictly lessflexible thanOs;a1 andOs;a2 .

Then, we enrichLs with abstract classes and interfaces,and obtainLa . We show that the first alternative is stillcomplete, while the Java rule and the second alternative ruleare not, and show how to make them complete.

Finally, we enrichLa allowing classes with many par-ents, and obtainLm corresponding to a language with bothinterfaces and multiple inheritance. We propose a soundand complete overloading framework forLa and brieflycompareLa with overloading resolution in C++.

4.1 Single inheritance

Underlying language framework The frameworkLs= (Ps ;Ms ;Cs ;ACs ; Is ;vs ;Ds rs ;CndMss ;Bs ;MSel s ; :s)defined below corresponds to a Java-like language with onlynon-abstract classes.

Assume thatp is a given well-formed program. Then:9This means that� is also anti-symmetric, hence the induced equivalence isequality.

1. Mps are all method names inp.

2. Cps are all the classes declared inp, andACps = Ips = ;.3. The subtyping relationvsp is the reflexive and tran-

sitive closure of theextends relation. Each classextends either one or no parent (for simplicity, we donot consider predefined classes likeObje t), andvspis acyclic (and hence a partial order).

4. Ds rps = Tps � (Tps)� � Tps . The three componentsare the type containing the method, the argument andthe result type, respectively.

5. Bps is the set of (compiled) method bodies inp.10

6. If class defines a body with namem, argument types�t, return typet and bodyb, thenb:psh 0; ht0;�t; tii foreacht02Tps and 0 vsp .

7. CndMssp(t0;m;�t) correspond to methods oft0 (ei-ther directly declared or inherited11) with namem andwhose argument types are supertypes of�t.

8. MSel sp( ;m; ht0;�t; ti)=� b, if declares a methodm with argument types�t, and bodyb (unique, by assumption (9) below),� MSel sp( 0;m; ht0;�t; ti)) otherwise, if 0 is the di-rect superclass of ,� none if has no superclass.

9. No class has two methods (directly declared or inher-ited) with same name and argument types but differentresult type.

From now on, we use the following abbreviations: for eachsubtyping relationv, t <p t0 iff t vp t0 and t 6= t0;t1:::tn vp t01:::t0n iff ti vp t0i for all 1� i�n; �t < �t0 iff�t vp �t0 and9i s.t.ti 6= t0i .Proposition 1 Ls is type safe.

Proof 1 Take a programp 2 Ps , 2 Cps , htr0;m;�tri 2Tps �Mps � (Tps)�, vsp tr0.Assume thatd2CndMs sp(tr0;m;�tr). Letd beht0;�t; ti. Fromthe definition ofCndMssp in (7), t0 declares a method withnamem, argument types�t and result typet, andtr0 vsp t0.Hence vsp t0. Then, from the definition ofvsp in (3), inherits from some 0 s.t. vsp 0 vsp t0 a method withnamem and argument types�t; from (9), this method hasreturn typet. Let b be the body of this method. Then,MSel sp( ;m; d) = b and, from (6),b:psh ; di. 210“Compiled method bodies” means that method calls are enriched with descrip-tors, and field accesses are enriched with class information; this is necessary for as-sumption (6), and also in any proof of type soundness of the language.11As already noticed, in Java inherited means not overridden.However, unless ex-plicitly indicated, in our formal treatment it makes no difference if overridden meth-ods are included.

The proof above, and the others in the sequel, are not,of course, complete proofs of the safety of the type sys-tem of the corresponding language; indeed, the notion oflanguage framework introduced in this paper abstracts frommany features only focusing on overloading resolution andrun-time selection. However, the result of type safety of thelanguage framework can be considered as the kernel of aproof of type soundness for the full language, as those pro-vided,e.g., for Java, in [9, 16, 18]. In particular, the typesystem should guarantee thatb:psh ; ht0; t1:::tn; tii holds ifb is a method body withn arguments, and replacing the re-ceiver by an object of class , and the arguments with valuesof subtypes oft1:::tn, gives a value of a subtype oft.

We show a simple condition, sufficient for soundness andcompleteness of more specific relations inLs .

Proposition 2 The semantic equivalence�t0p onDs rps co-incides with equality of argument types.

Proof 2 From the definition ofMSel s , which only dependson argument types.2Overloading frameworks We define three overload-ing frameworks withLs as the underlying language frame-work, which correspond to the three rules informally intro-duced in section 2.2.� Os;j = hLs ;� j i corresponds to the Java rule,� Os;a1 = hLs ;�a1 i describes the first alternative,� Os;a2 = hLs ;�a2 i describes the second alternative.

Definition 7 For anyp2P, ht0;�t; ti, ht00;�t0; t0i2Ds rps ,� ht0;�t; ti � jpht00;�t0; t0i iff �t vsp �t0 andt0 vsp t00,� ht0;�t; ti �a1p ht00;�t0; t0i iff �t vsp �t0,� ht0;�t; ti �a2p ht00;�t0; t0i iff �t vsp �t0 andt0 = t00,or t0 <sp t00.

The three more specific relations,� jp, � a1p and� a1p , arewell-defined, since they are pre-orders on the whole setof descriptorsDs rs . Note that, if overridden methods arenot considered, then the three pre-orders correspond to dif-ferent ways of combining the subtype relations on the first(declaring class) and second (argument types) componentof Ds rs , that is, componentwise, from right to left (whichonly considers the argument types), and from left to right.

The relations� jp,�a1p and�a1p are defined on the sameset of descriptorsDs rs . This allows a better comparison.However, the first component inDs rs is not required forLs , nor for the first alternative,�a1 , but is required for� jand� a2 . This reflects the fact that� a1 has the simplestcopy semantics.

We show that the three more specific relations are soundand complete.

Lemma 3 For anyp2P, if d = ht0;�t; ti; d0 = ht00;�t; t0i2Ds rps are two candidates for some call inp, thent = t0 andeithert0 vsp t00 or conversely.

Proof 3 By the definition of candidates in (7), the fact thateach class has at most one parent class (3) and the assump-tion in (9). 2Proposition 3 � j , � a1 and� a2 are sound and completew.r.t.Ls .

Proof 4 � j : It is easy to see that, for anyp 2 Ps , the

equivalence��jp on maximally specific candidates is equal-ity, since by assumptions (3) and (9),� jp is a partial orderover candidates for a given call. Hence soundness followsfrom lemma 2. For completeness, assume thatd = ht0;�t; tiand d0 = ht00;�t0; t0i are two semantically equivalent max-imally specific candidates. From Prop.2,�t = �t0 and fromLemma 3,t = t0 and eithert0 vsp t00, or conversely. Henced � jpd0 or conversely hence, from Lemma 1, we can con-

clude thatd ��jp d0. 2� a1 : Equivalence��a1p is (by assumption (3)) equalityof argument types. The rest follows from Prop.2.2�a2 : The same proof as for� j applies. 2We show now that the alternative rules are strictly more flex-ible than the Java rule.

Lemma 4 If � is a pre-order over a setDs, and there existsx2Ds, s.t.x � y 8y2Ds, thenx is a minimal element andany other minimal element is equivalent tox.

Proposition 4 �a1 and�a2 are strictly more flexible than� j w.r.t.Ls .

Proof 5 � a1 : First we show that� a1 is more flexiblethan� j . Consider an unambiguous call w.r.t.� jp in a pro-gramp. Since� jp is a partial order, there exists exactly onedescriptor, sayd, which is more specific than all the candi-dates w.r.t.� jp. Since� jp implies� a1p , d is more specificthan all the candidates w.r.t.�a1p as well, By Lemma 4d ismaximally specific for� a1p (hence the second condition indefinition 6 is satisfied) and the call is unambiguous w.r.t.� a1p (hence the first condition in definition 6 is satisfied).To show that there are calls which are ambiguous w.r.t.� jand unambiguous w.r.t.� a1 , consider the example 1 insection 2.2, where the candidates for the call :m(b0) arehA;B0; inti andhB;A0; inti. 2� a2 : To show that� a2 is more flexible than� j , sincethey are partial orders, it is enough to note that� jp implies� a2p . To show that there are calls which are ambiguousw.r.t.� j and unambiguous w.r.t.� a1 , consider again ex-ample 1. 2Finally, the alternatives� a1 and� a2 are not comparable:There exist calls which are ambiguousw.r.t. to � a1 andunambiguousw.r.t.�a2 , and conversely,c.f.App. D and E.

4.2 Single inheritance with abstract methods

We enrich Ls with abstract classes and interfaces, ob-taining frameworkLa = (Pa ;Ma ;Ca ;ACa ; Ia ;va ;Ds ra ;CndMsa ;Ba ;MSela ; :a ). We only list the components andassumptions which are different fromLs .

2. ACpa andIpa are abstract classes and interfaces declaredin p, respectively.

3. The subtyping relationvap is the reflexive and transi-tive closure of the union of theextends andim-plements relations. Same assumptios as forvsp.

4. Ds rpa=Kinda�Tpa�(Tpa)��Tpa , withKinda=fa;:ag;a, :a indicate abstract and non-abstract methods.

10. For each 2 (Cps n ACpa), if vap t and t declaresan abstract method, then directly declares or inher-its a non-abstract method with the same name and ar-gument types (which has the same return type by as-sumption (9)).

Proposition 5 La is type safe.

Proof 6 The proof is analogous to that for Prop.1. Herewe apply (10) which ensures that, since vap t0, declaresor inherits one non-abstract method with namem and ar-gument types�t. 2We extend the three more specific relation from section

4.1 toDs rpa , in the trivial way, by disregarding the kindcomponent. Then, the first alternative,� j , is still soundand complete, but� j and�a2 are sound but in-complete.

Proposition 6 1. �a1 is sound and complete w.r.t.La .

2. � j and�a2 are sound, but not complete w.r.t.La .

Proof 7 1. Proof is same as forLs , in Prop.3. 22. The proof of soundness is the same as forLs , in Prop.3.To show that completeness does not hold, assume a programp as in the counterexample 2 in section 2.3, containingI, I1,I2 and some classes implementingI. Thenha; I1; (); inti 6�jpha; I2; (); inti and ha; I2; (); inti 6� jpha; I1; (); inti; thesame for� a2p . However, for all implementingI,MSelap ( ;m; ha; I1; (); inti) = MSelap ( ;m; ha; I2; (); inti).2To achieve completeness,� j and�a2 need to be modified,so that no ambiguity arises from different abstract methodswith same argument types. For this, kind information willbe used, although�a1 considers only the argument types.

Definition 8 For p2Pa ; hk; t0;�t; ti; hk0; t00;�t0; t0i2Ds rpa :� hk; t0;�t; ti� j+p hk0; t00;�t0; t0i iff(1) t0 vap t00 and �t vsp �t0 or(2) �t = �t0 and t00 6vap t0 and k0 = a

� hk; t0;�t; ti�a2+p hk0; t00;�t0; t0i iff(1) t0 <ap t00 or (t0 = t00 and�t vap �t0) or(2) �t = �t0 and t00 6vap t0 and k0 = a.Def.8 extends Def.7; we added case (2), which makes amethod more specific than another, when they have thesame argument types and the latter is abstract (unless de-clared in a heir class). The definition of� j+ correspondsto overloading resolution as in the revised Java specification[4], in 15.12.2.2. We prove now that the more specific rela-tions defined above are well-defined, sound and complete.

Lemma 5 For any p 2 Pa , if d = hk; t0;�t; ti; d0 =hk0; t00;�t; t0i2Ds rpa are two candidates for some call inp,thent = t0 and eithert0 vap t00 or conversely, or at leastone offk; k0g is a.Proof 8 By the definition of candidate methods in (7), thefact that each class has at most one parent class (3) andassumption (9).2Proposition 7 � j+ and�a2+ are well-defined, sound andcomplete w.r.t.La .

Proof 9 We give the proof for� j+, the other case is anal-ogous.

Take anyd; d0; d002MaxMs�j+p(t0;m;�t) for somet0;m;�t. As-sume thatd = hk; t0;�t; ti; d0 = hk0; t00;�t0; t0i, and d00 =hk00; t000 ;�t00; t00i.

We first prove that� j+ is a pre-order on the set of max-imally specific candidates, i.e., that it is transitive. Assumethat d � j+p d0 � j+p d00. If d � j+p d0 holds by (1), then it

must bed = d0 (sinced ��j+p d0 holds by Lemma 1), henced � j+p d00. Analogously, ifd0 � j+p d00 holds by (1), then itmust bed0 = d00, henced � j+p d00. Finally, if bothd � j+p d0andd0 � j+p d00 hold by (2), then the thesis holds since ei-ther t000 6vap t0 (henced � j+p d00 by (2)), ord00 � j+p d henced � j+p d00 too must hold by Lemma 1.

It is easy to see that��j+p can be characterized as follows:d ��j+p d0 iff�t = �t0 and (t0 = t00 or t0 6vap t00; t00 6vap t0; k = k0 = a)Then, soundness follows from Prop.2. For completeness,assume thatd andd0 are two semantically equivalent max-imally specific candidates, hence, from Prop.2,�t = �t0 and,from lemma 5,t = t0 and eithert0 vap t00 or conversely,or at least one offk; k0g is a. In the first case,d � j+p d0or conversely, hence we can conclude by Lemma 1; in thesecond case, if, e.g.,k0 = a, thend � j+p d0 and the thesisfollows analogously.24.3 Multiple inheritance

We define an overloading frameworkOm = hLm ;�mifor a paradigmatic language supporting both multiple inher-itance and abstract methods, as shown in section 2.4. This

framework is an extension ofLa , with which we explorethe new issues introduced when dropping the assumptionthat a class extends at most one parent. We also intro-duce the distinction between virtual and non-virtual meth-ods which was not significant in the preceding frameworks.Method selection, consequently, is dynamic only for ab-stract or virtual methods, while for non-virtual methods theselected body corresponds to the descriptor determined byoverloading resolution.Lm differs fromLa in that:

3. A class can have many parent classes.

4. Ds rpm= Kindm � Tpm � (Tpm)� � Tpm ,Kindm = fa; v;:vg.8. MSelmp ( ;m; hk; t0;�t; ti)=� if k = :v, then

– b if t0 declares a methodm with argumenttypes�t and bodyb,

– none otherwise;� otherwise,

– b, if declares a virtual methodm with argu-ment types�t and bodyb (unique by assump-tion (9)),

– b, if MSelmp ( 0;m; hk; t0;�t; ti)) = b forsome 0 direct superclass of , and this defi-nition does not depend on the choice of 012

– none otherwise.

10. For each 2 (Cps n ACpa), if vap t and t declaresan either virtual or abstract method, then directlydeclares or inheritsexactly onenon-abstract methodwith the same name and argument types (which hasthe same return type by assumption (9)).

Proposition 8 Lm is type safe.

Proof 10 The proof is analogous to those provided forLs(Prop.1) andLa (Prop.5); the only difference is that, in thecasek 2 fa; vg, we have to apply the new version of (10). Inthe casek = :v, method selection directly gives the methodbody corresponding tod, and the thesis holds trivially.2We define sound and complete more specific relation�m :Definition 9 For p 2 Pm , hk; t0;�t; ti, hk0; t00;�t0; t0i2Ds rpm ,hk; t0;�t; ti �mp hk0; t00;�t0; t0i iff(1) �t <mp �t0 or(2) �t = �t0 and(t0 vmp t00 or (t00 6vmp t0, k0 = a, k 6= :v)).12Thus, method selection would returnnone, if two superclasses which were notsubclasses of each other contained a method body with appropriate argument types.

Informally, a method is more specific than another iff either(1) it has (strictly) more specific argument types or (2) theyhave the same argument types and either the former over-rides the latter, or the latter is abstract (and does not over-ride the former) and the former is either abstract or virtual.We can prove that the more specific relation defined aboveis well-defined, sound and complete.

We first give a sufficient condition which guaranteessoundness and completeness for overloading resolution inLm , analogous to that provided forLs in Prop.2. Since wehave introduced non-virtual methods, two descriptors arenow semantically equivalent if either they are both abstractor virtual and they have the same argument types (sincein this case method selection only depends on argumenttypes), or they are both non-virtual and they have the sameargument types and are declared in the same class (that is,are the same method) .

Proposition 9 For anyp 2 Pm , and anyt0;m;�t :hk; t0;�t; ti �t0p hk0; t00;�t0; t0i iff�t = �t0 and(k; k0 6= :v or t0 = t00).Proof 11 From the definition ofMSel s . 2Proposition 10 � m is well-defined, sound and completew.r.t.Om .

Proof 12 The proof that� m is a pre-order on the set ofmaximally specific candidates can be done by case analysis,analogously to that provided for� j+ in Prop.7. It is easy

to see that��mp can be characterized as follows:d ��mp d0 iff�t = �t0 and((t0 = t00) or (t0 6�mp t00; t00 6�mp t0; k = k0 = a)).This condition implies�t = �t0 and(k; k0 6= :v or t0 = t00),hence soundness follows by Prop.9. For completeness, wehave to show the converse. Indeed, ifd; d0 are semanti-cally equivalent maximally specific candidates, then eithert0 = t00, henced ��mp d0, or k; k0 6= :v. In this case: ift0 vmp t00 thend �mp d0, henced ��mp d0 by Lemma 1, andanalogously ift00 vmp t0; if d 6� mp d0; d0 6� mp d, then eitherk = k0 = a, henced ��mp d0 , or, e.g.,k = v, but in thiscase it must bek0 = a for assumption (10), henced �mp d0,henced ��mp d0 by Lemma 1. 2Comparison with C++ The motivation forOm camefrom multiple inheritance as in C++. However, because wehadLa , we developedOm as an extension ofLa . There-fore,Om and C++ are similar in some aspects, and differentin others:

Both Om and C++ adopt the arguments-only rule andassumptions analogous to those in (10). However, C++andOm differ in the following aspects: C++ candidate

sets do not contain methods from a superclass if the cur-rent class contains a method definition with the same name(see App.B). Also,� m in Om is complete, whereas inC++ the conflict between several inherited abstract meth-ods makes a call ambiguousc.f. example 2. Last,Om doesnot model many C++ specific featurese.g., using-clauses,private members, non-virtual inheritance.We plan extensions of the model to deal with these issues.

5 Applicability of the frameworks

In our frameworks static resolution is modelled by thefunction CndMs , which defines candidates for methodcalls, and by the relation� which selects maximally spe-cific candidates. Dynamic resolution is modeled by thefunctionMSel .

In this paper we focused on different more specific re-lations, and therefore kept the definitions ofCndMs andMSel fixed. However, the framework can be adapted torepresent many more language features:� Private members are not inherited (but may be redefined)in subclasses. For that,Kind should also account for ac-cess modifiers. The domain ofCndMs would be extendedto: Cp� Tp�Mp� Tp� and the first argument, represent-ing the class containing the method call, would be used tofilter out private methods.MSel would start looking-up inthe first superclass of the dynamic receiver’s class which in-herits the method from the descriptor –c.f. [2] for details.� Contravariant overriding, whereby a method overrides aparent’s method with more specific argument and less spe-cific return types, can be expressed by suitable definitionsof CndMs , and ofMSel .� Multimethods would require theMSel function to takeinto account the dynamic class of all, or some, arguments,as well as that of the receiver.

In further work we plan to analyze these possibilities,through different extensions of our framework.

6 Conclusions

We have discussed cases where programming languagestreat the interaction between overloading resolution and in-heritance in counterintuitive and restrictive ways.

In order to clarify the issues involved in this interaction,we have developed a formal notion ofoverloading frame-workwhich describes static and dynamic function selection,abstracting from other language features. We have definedthe following properties of an overloading framework:� type safety: guarantees that all candidate method de-

scriptors for a given call lead at run-time to a correctbody,

� soundness: guarantees that all method descriptorswhich have distinct dynamic semantics are distin-guished by overloading resolution,� completeness: guarantees that all method descrip-tors which are distinguished by overloading resolutionhave distinct dynamic semantics,� flexibility: allows as many calls as sensible to be un-ambiguous.

We have demonstrated that Java overloading resolution inthe first 1996 version [11] is type safe, sound but not com-plete, while in the 2000 version [4] it is complete but notas flexible as could be. We have suggested two alternativeapproaches, which are type safe, sound, complete and moreflexible than those of Java. We have also defined a soundand complete framework for overloading and inheritance inlanguages with multiple inheritance.

The main outcome of our work is the definition of aframework in which to study in a formal way the interactionbetween static overloading resolution (overloadingin theterminology of this paper) and dynamic overloading resolu-tion (overriding), abstracting from other language features.With such frameworks one can express the “overall idea” ofthe languages design, which gets lost in the many details ofcomplete systems as usually described through operationalsemantics, type systems, and subject reduction proofs.

In this paper we have focused on different ways of defin-ing the more specific method, but through modification ofother components of the framework (CndMs , MSel , Ds r)we shall be able to characterize other features, such as pri-vate methods, multimethods, non-virtual inheritanceetc.

Finally, in the paper we have informally shown that var-ious overloading policies correspond to different copy se-mantics for inheritance. We have also seen that the systemswith best properties are those with the simplest copy seman-tics. It is an interesting open question in how far the copy se-mantics could be automatically derived from the overload-ing and method selection definition.

Acknowledgments

We are grateful to Giovanni Lagorio for useful discus-sions, and to the anonymous FOOL’8 referees for theirsuggestions. This work was partially supported by Murst- TOSCA Teoria della Concorrenza, Linguaggi di OrdineSuperiore e Strutture di Tipi, APPlied SEMantics - EspritWorking Group 26142 and by the EPSRC (Grant Ref: GR/L76709).

References

[1] M. Abadi and L. Cardelli.A Theory of Objects. Mono-graphs in Computer Science. Springer Verlag, NewYork, 1996.

[2] D. Ancona and E. Zucca. True modules for Javaclasses. Technical Report DISI-TR-00-12, Diparti-mento di Informatica e Scienze dell’Informazione,Università di Genova, August 2000. Submitted forpublication.

[3] D. Ancona, E. Zucca, and S. Drossopoulou. Overload-ing and inheritance in Java (extended abstract). In2thWorkshop on Formal Techniques for Java Programs,June 2000.

[4] G. Bracha, J. Gosling, B. Joy, and G. Steele.The JavaTM Language Specification, Second Edition.Addison-Wesley, 2000.

[5] L. Cardelli and P. Wegner. On understanding types,data abstraction and polymorphism.ACM ComputingSurveys, 17(4):471–522, 1985.

[6] G. Castagna.Object-Oriented Programming: A Uni-fied Foundation. Progress in Theoretical ComputerScience. Birkhäuser, 1997.

[7] C. Chambers. Object-oriented multi-methods in Ce-cil. In ECOOP ’92, number 615 in Lecture Notes inComputer Science, Berlin, 1992. Springer Verlag.

[8] W. Cook. A proposal for making Eiffel type-safe. InS. Cook, editor,ECOOP ’87, pages 57–70, Notting-ham, July 1989. Cambridge University Press.

[9] S. Drossopoulou and S. Eisenbach. Describing thesemantics of Java and proving type soundness. InJ. Alves-Foss, editor,Formal Syntax and Semantics ofJava, number 1523 in Lecture Notes in Computer Sci-ence, pages 41–82. Springer Verlag, Berlin, 1999.

[10] K. Fisher, F. Honsell, and J. C. Mitchell. A LambdaCalculus of Objects and Method Specialization. InNordic Journal of Computing 1(1), pages 3–37, 1994.

[11] J. Gosling, B. Joy, and G. Steele.The JavaTM Lan-guage Specification. Addison-Wesley, 1996.

[12] S.C. Keene.Object Oriented Programming in Com-mon Lisp: A Programming Guide in CLOS. Addison-Wesley, 1989.

[13] Bertrand Meyer. Static typing and other mys-teries of life. Electronic note available athttp://http://www.eiffel.com.

[14] R. Milner, M. Tofte, and R. Harper.The Definitionof Standard ML. The MIT Press, Cambridge, Mas-sachussetts, 1990.

[15] B. Stroustrup. The C++ Programming Language.Reading. Addison-Wesley, MA, USA, special edition,2000.

[16] D. Syme. Proving Java type sound. In Jim Alves-Foss, editor,Formal Syntax and Semantics of Java,number 1523 in Lecture Notes in Computer Science,pages 83–118. Springer Verlag, 1999.

[17] US Department of Defense.Reference Manual for theAda Programming Language, 1983. ANSI/MIL-STD-1815 A.

[18] D. von Oheimb and T. Nipkow. Machine-checking theJava specification: Proving type-safety. In Jim Alves-Foss, editor,Formal Syntax and Semantics of Java,number 1523 in Lecture Notes in Computer Science,pages 119–156. Springer Verlag, 1999.

A A program in an overloading framework

The following sets, functions and predicates come out ofthe application of theOs;j overloading framework to pro-gramp0, which stands for the first example in section 2.1:� Mp0s = fmg,� Cp0s = fA;B;A0;B0;C0g, Ip0s = ; = ACp0s ,� B vsp0 A, B0 vsp0 A0, C0 vsp0 B0,� Ds rp0s = fhA;A0; inti; hB;B0; intig� CndMssp0(hA;m;Ai) = ;,CndMssp0(hA;m;A0i) = fhA;A0; intig,CndMssp0(hB;m;B0i) = fhA;A0; inti; hB;B0; intig,

etc.� :ps = f f return 1g; hA;A0; inti; f return 2g; hB;B0; intig.� hB;B0; inti � jp0hA;A0; inti� MSel sp0(A; hA;A0; inti) = f return 1gMSel sp0(B; hA;A0; inti) = f return 1gMSelp0( A; hB;B0; inti) = noneMSel sp0(B; hB;B0; inti) = f return 2gB Overloading resolution in C++

Here we demonstrate in terms of some examples howcandidate methods are selected in C++. Candidate methodsare all the methods declared (or imported viausingclauses)in thefirst parent class of which hassomemethod with thesame name as in the call. Consider the following example.

Example 4class A { int m(B’ x) return 1; }class B : public A { int m(A’ x) return 2; }class C : public B { }

In the call :m(b0) the method declared inB is selected.This resembles the second alternative, but note that themethod inB would be selected even in

class A { int m(B’ x) return 1; }class B : public A { int m(C’ x) return 2; }class C : public B { }

with C0 arbitrary class; in this case the call would be ill-formed, while the second alternative selects the method de-clared inA. On the contrary, in

Example 5class A { int m(B’ x) return 1; }class B : public A { using A :: m;

int m(A’ x) { return 2; } }class C : public B { }

in the method call :m(b0) the method declared inA is se-lected. This demonstrates that a method is considered morespecific than another based on argument types only. Thus,the first alternative is adopted, but on a different set of can-didates.

Copy semantics Following the C++ rule, the example 4would be transformed as follows.

class A { int m(B’ x) return 1; }class B : public A { int m(A’ x) return 2; }class C : public B { int m(A’ x) return 2; }

The example 5 would be transformed as follows.

class A { int m(B’ x) return 1; }class B : public A { int m(B’ x) return 1; }

int m(A’ x) return 2; } }class C : public B { int m(B’ x) return 1; }

int m(A’ x) return 2; } }

C The pre-order � j+pThe following example illustrates why� j+p is not a pre-

order onDs rp. In fact,� j+p is not a pre-order on the can-didate methods either!

abstract class P { abstract void m(B’ x)void m(A’ x) { } }

interface I { void m(B’ x) }class H extends P implements I { }

The candidate methods forh:m(b0), with h of typeH (re-member thatB0 is a subclass ofA0), are the two methods

from P and that fromI, i.e., the candidate method descrip-tors aref ha;P;B0; voidi; h:a;P;A0; voidi; ha; I;B0; voidi g.With p0 standing for the above program, the Java relation� j+ from Sect. 4.2 gives:ha;P;B0; voidi;� j+p0 ha; I;B0; voidi, andha; I;B0; voidi;� j+p0 ha;P;B0; voidi, andha; I;B0; voidi;� j+p0 h:a;P;A0; voidi, butha; I;B0; voidi6� j+p0 h:a;P;A0; voidi,therefore� j+p0 is notand ordering relation onDs rp0.

The set of maximally specific method descriptors how-ever, is onlyf ha;P;B0; voidi; ha; I;B0; voidi g,on which set� j+p0 is a pre-order.

D �a1 is not more flexible than�a2The following example demonstrates that� a1 is not

more flexible than� a2 : The callb:m(b0; b0) is ambigu-ousw.r.t. � a1 , but un-ambiguousw.r.t. � a2 – the methodfromB would be selected:

class A { void m (A’ x, B’ y) { } }class B extends A { void m (B’ x, A’ y) { } }

E �a2 is not more flexible than�a1The following example demonstrates that� a2 is not

more flexible than� a1 : The callb:m(b0; b0) is ambigu-ousw.r.t. � a2 , but un-ambiguousw.r.t. � a1 – the methodfromA would be selected:

class A { void m (B’ x, B’ y) { } }class B extends A { void m (B’ x, A’ y) { }

void m (A’ x, B’ y) { } }