Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'Abstract classes, Interfaces, and Patterns

A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here.

29.  Method Combination

In this section we will primarily study method combination. Secondarily we will touch on a more specialized, related problem called parameter variance.

29.1 Method Combination29.3 Covariance and Contravariance
29.2 Parameter Variance
 

29.1.  Method Combination
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

If two or more methods, of the same name, located different places in a class hierarchy, cooperate to solve some problem we talk about method combination.

A typical (and minimal) scene is outlined in Figure 29.1. Class B is a subclass of A, and in both classes there is a method named Op. Both Op methods have the same signature.

Figure 29.1    Class B is a subclass of class A

Overall, and in general, there are several ways for Op in class A and B to cooperate. We can, for instance, imagine that whenever a B-object receives an Op message, both operations are called automatically. We can also imagine that Op in class A is called explicitly by Op in class B, or the other way around.

Along the lines outlined above, we summarize two different method combination ideas. The first is known as imperative method combination, and the second is known as declarative method combination.

  • Programmatic (imperative) control of the combination of Op methods

    • Superclass controlled: The Op method in class A controls the activation of Op in class B

    • Subclass controlled: The Op method in class B controls the activation of Op in class A

    • Imperative method combination

  • An overall (declarative) pattern controls the mutual cooperation among Op methods

    • A.Op does not call B.Op   -   B.Op does not call A.Op.

    • A separate abstraction controls how Op methods in different classes are combined

    • Declarative method combination

Mainstream object-oriented programming languages, including C#, support imperative method combination. Most of them support the variant that we call subclass-controlled, imperative method combination.

Beta [Kristensen87] is an example of programming language with superclass-controlled, imperative method combination. CLOS [Steele90, Keene89] is one of the few examples of programming languages with declarative method combination. (The interested reader can consult Chapter 28 of [Steele90] to learn much more about declarative method combination in CLOS. It is available on the web - just follow the given link a couple of levels.)

C# supports subclass controlled, imperative method combination via use of the notation base.Op(...)

The notion base.Op(...) has been discussed in Section 28.7 and it has been illustrated in Program 26.2 (line 17), Program 28.13 (line 20), and Program 28.14 (line 20).

 

29.2.  Parameter Variance
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

We will continue the discussion of the scene outlined in Figure 29.1, now refined in Figure 29.2 shown below. The question is how the parameters of Op in class A and B vary in relation the variation of type A and type B.

Figure 29.2    Class B is a subclass of class A, and T is a subclass of S.

In Program 29.1 we create an object of the specialized class B (in line 2), and we assign it to a variable of static type A (line 5) This is possible due to polymorphism. In line 6 we send the Op message to the B object. We assume that Op is virtual, and therefore we expect that Op in class B is called.

So far so good. The thing to notice is that Op takes a single parameter. If we pass an instance of class S to B.Op we may be in deep trouble. A problem occur if B.Op applies some operation from class T on the S object.

1
2
3
4
5
6
7
   A aref;
   B bref = new B();
   S sref = new S();

   aref = bref;    // aref is of static type A and dynamic type B
   aref.Op(sref);  // B.Op is called with an S-object as parameter.
                   // What if an operation from T is activated on the S-object?
Program 29.1    An illustration of the problems with covariance.

Below, in Program 29.2 (only on web) we show a complete C# program which illustrates the problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;

class S{
  public void Sop(){
   Console.WriteLine("Sop");
  }
}

class T:S{
  public void Top(){
   Console.WriteLine("Top");
  }
}

class A {
 public void Op(S x){
   x.Sop();
 }
}

class B: A {
 public void Op(T x){
   x.Top();
 }
}

class Client{
 public static void Main(){
   A aref;
   B bref = new B();
   S sref = new S();

   aref = bref;    // aref is of static type A and dynamic type B
   aref.Op(sref);  // B.Op is called with an S-object as parameter.
                   // What if an operation from T is activated on the S-object?
 }
}
Program 29.2    The full C# program.

The story told about the scene in Program 29.1 and Program 29.2 (only on web) turns out to be flawed in relation to C#! I could have told you the reason, but I will not do so right away. You should rather take a look at Exercise 8.1 and learn the lesson the hard way. (When access is granted to the exercise solutions, you will be able to get my explanation).

It turns out that parameter variance is not really a relevant topic in C#...

 

29.3.  Covariance and Contravariance
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

The situation encountered in Figure 29.2 of Section 29.2 is called covariance, because the types S and T (as occurring in the parameters of Op in class A and B) vary the same way as classes A and B. (The parameter type T of Op in class B is a subclass of the parameter type S of Op in class A; The class B is a subclass of class A; Therefore we say that T and S vary the same way as A and B. )

  • Covariance: The parameters S and T vary the same way as A and B

As a contrast, the situation in Figure 29.3 below is called contravariance, because - in this variant of the scene - S and T vary in the opposite way as A and B. Please compare carefully Figure 29.2 with Figure 29.3.

  • Contravariance: The parameters S and T vary the opposite way as A and B

Figure 29.3    Class B is a subclass of class A, and the parameter class S is a subclass of T.

As we will see in Exercise 8.1 the distinction between covariance and contravariance is less relevant in C#. However, covariance and contravariance show up in other contexts of C#. See Section 42.6.


Exercise 8.1. Parameter variance

First, be sure you understand the co-variance problem stated above. Why is it problematic to execute aref.Op(sref)in the class Client?

The parameter variance problem, and the distinction between covariance and contravariance, is not really a topic in C#. The program with the classes A/B/S/T on the previous page compiles and runs without problems. Explain why!

Solution


 

29.4.  References
[Keene89]Sonya E. Keene, Object-Oriented Programming in Common Lisp. Addison-Wesley Publishing Company, 1989.
[Steele90]Guy L. Steele, Common Lisp, the language, 2nd Edition. Digital Press, 1990.
[Kristensen87]Bent Bruun Kristensen, Ole Lehrmann Madsen, Birger Møller-Pedersen and Kristen Nygaard, "The BETA Programming Language". In Research Directions in Object-Oriented Programming, The MIT Press, 1987. Bruce Shriver and Peter Wegner (editors)

Generated: Monday February 7, 2011, 12:18:13
Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'