digitalmars.D - Contravariance (is this a bug)
- Jesse Phillips (29/29) Jul 26 2010 Contravariance allows derived classes to return from a function any deri...
- Tomek =?UTF-8?B?U293acWEc2tp?= (3/48) Jul 26 2010 Yep, it's a bug. File it (but with a _minimal_ test-case).
- bearophile (5/6) Jul 26 2010 I have added it:
- Norbert Nemec (15/44) Jul 26 2010 In fact, the code contains a bug inside the A_Parser.get function which
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
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
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
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