www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Contravariance (is this a bug)

reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Contravariance allows derived classes to return from a function any derived
class of what the parent class returns. I have discovered that if you claim to
return a derived class, you can still return the parent class. In the example
below, A_Parser is returning Report[] from a function that claims to return
A_Report[]. I'm thinking this is a bug, is there any reason it wouldn't be?

import std.stdio;

class A_Parser : Parser {
   Report[string] stuff;

   this() {
      stuff = ["hi": new A_Report("Bye")];
   }

   override A_Report get(string uuid) {
      return stuff[uuid];
   }
}

class A_Report : Report {
   string value;
   this(string val) {
      value = val;
   }

   void print() {
      writeln(value);
   }
}

abstract class Parser {
   abstract Report get(string);
}

class Report {
}

void main() {
   auto a = new A_Parser();

   a.get("hi").print;

}
Jul 26 2010
next sibling parent reply Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
Jesse Phillips wrote:

 Contravariance allows derived classes to return from a function any
 derived class of what the parent class returns. I have discovered that if
 you claim to return a derived class, you can still return the parent
 class. In the example below, A_Parser is returning Report[] from a
 function that claims to return A_Report[]. I'm thinking this is a bug, is
 there any reason it wouldn't be?
 
 import std.stdio;
 
 class A_Parser : Parser {
    Report[string] stuff;
 
    this() {
       stuff = ["hi": new A_Report("Bye")];
    }
 
    override A_Report get(string uuid) {
       return stuff[uuid];
    }
 }
 
 class A_Report : Report {
    string value;
    this(string val) {
       value = val;
    }
 
    void print() {
       writeln(value);
    }
 }
 
 abstract class Parser {
    abstract Report get(string);
 }
 
 class Report {
 }
 
 void main() {
    auto a = new A_Parser();
 
    a.get("hi").print;
 
 }

Yep, it's a bug. File it (but with a _minimal_ test-case). Tomek
Jul 26 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Tomek S.:
 Yep, it's a bug. File it (but with a _minimal_ test-case).

I have added it: http://d.puremagic.com/issues/show_bug.cgi?id=4511 Bye, bearophile
Jul 26 2010
prev sibling parent Norbert Nemec <Norbert Nemec-online.de> writes:
In fact, the code contains a bug inside the A_Parser.get function which 
implicitely converts stuff from type Report to type A_Report. If you 
change the declaration of stuff to
	A_Report[string] stuff;
everything should be fine.

Furthermore, your comments seems to confuse the terms co- and 
contra-variance. The interface of of A_Parser.get does in fact 
demonstrate "co-variance": output types of overriding methods must be 
subtypes of the original methods output. (They have the same direction 
of inheritance as the enclosing class, hence "co-")

Input type, on the other hand are "contra-"variant. An overriding method 
must accept as input any *super*-type of input types of the original.

Greetings,
Norbert


On 26/07/10 17:46, Jesse Phillips wrote:
 Contravariance allows derived classes to return from a function any derived
class of what the parent class returns. I have discovered that if you claim to
return a derived class, you can still return the parent class. In the example
below, A_Parser is returning Report[] from a function that claims to return
A_Report[]. I'm thinking this is a bug, is there any reason it wouldn't be?

 import std.stdio;

 class A_Parser : Parser {
     Report[string] stuff;

     this() {
        stuff = ["hi": new A_Report("Bye")];
     }

     override A_Report get(string uuid) {
        return stuff[uuid];
     }
 }

 class A_Report : Report {
     string value;
     this(string val) {
        value = val;
     }

     void print() {
        writeln(value);
     }
 }

 abstract class Parser {
     abstract Report get(string);
 }

 class Report {
 }

 void main() {
     auto a = new A_Parser();

     a.get("hi").print;

 }

Jul 26 2010