www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cannot implicitly convert derived type

reply "Frustrated" <c1514843 drdrb.com> writes:
interface iGui
{
	 property iButton button(ref iButton button);
}

class WindowsGui : iGui
{
	WindowsButton _button;

	 property WindowsButton button(ref WindowsButton button)
	// property iButton button(ref iButton button)
	{
		_button = button;
		return button;
	}
}

interface iButton { }
class WindowsButton : iButton { }


Should this not work?

Error: class main.WindowsGui interface function 'iButton
button(ref iButton
button)  property' is not implemented	

Or by using the commented line:

Error: cannot implicitly convert expression (button) of type
main.iButton to main.WindowsButton	


1. In the first case I override a property using a more derived
type. This should work but doesn't. Seems D doens't support
covariance properly?

2. In the second case, I can cast to make everything work. This
seems wrong. Hence goto 1. WindowsGui is designed to only work
with WindowsButton, say, and I should never have to use iButton
in the WindowsGui class unless, maybe, I want to support
non-windows buttons in the WindowsGui for some reason.

Basically, because of the covariance issue I end up having to use
a lot of casts. Hopefully theres some simple trick that won't
pollute the code to make this work. I guess I could use a
templated property with a generic type that is derivable from
iButton to make it work?

In some sense I can understand the error. If I'm using iGui then
I have the option to use any button(since it is generic) but if
iGui is a WindowsGui I'm not allowing this. The issue is, that I
will have some type of dependency restrictions on the types.

e.g.,

iGui g = new WindowsGui;

g.button = new LinuxButton; // ok but not ok!! (should result in
an error in some way)

Obviously I can cast and check the type and do all that. Just
feels like the wrong way to go about it because it requires a lot
of casting and polluting the code with checks that in general,
should be unnecessary. Again: In the WindowsGui I want to use
WindowsButton, not iButton because WindowsGui will never need any
other type of button. iButton is too general to use in WindowsGui.

(it would be cool if one could do something like

class WindowsGui : iGui
     iButton <= WindowsButton // constrains iButton to always be a
WindowsButton. Checks/casts are automatically added by compiler
when necessary
{
     // use WindowsButton here with proper covariance relations and
checks/casts
}

Anyways, hopefully there is some single trick to get what I'm
asking?
Feb 21 2014
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/21/2014 02:54 PM, Frustrated wrote:
 interface iGui
 {
       property iButton button(ref iButton button);
 }

 class WindowsGui : iGui
 {
      WindowsButton _button;

       property WindowsButton button(ref WindowsButton button)
      // property iButton button(ref iButton button)
      {
          _button = button;
          return button;
      }
 }

 interface iButton { }
 class WindowsButton : iButton { }


 Should this not work?

 Error: class main.WindowsGui interface function 'iButton
 button(ref iButton
 button)  property' is not implemented

 Or by using the commented line:

 Error: cannot implicitly convert expression (button) of type
 main.iButton to main.WindowsButton


 1. In the first case I override a property using a more derived
 type. This should work but doesn't. Seems D doens't support
 covariance properly?

 2. In the second case, I can cast to make everything work. This
 seems wrong. Hence goto 1. WindowsGui is designed to only work
 with WindowsButton, say, and I should never have to use iButton
 in the WindowsGui class unless, maybe, I want to support
 non-windows buttons in the WindowsGui for some reason.

 Basically, because of the covariance issue I end up having to use
 a lot of casts. Hopefully theres some simple trick that won't
 pollute the code to make this work. I guess I could use a
 templated property with a generic type that is derivable from
 iButton to make it work?

 In some sense I can understand the error. If I'm using iGui then
 I have the option to use any button(since it is generic) but if
 iGui is a WindowsGui I'm not allowing this. The issue is, that I
 will have some type of dependency restrictions on the types.

 e.g.,

 iGui g = new WindowsGui;

 g.button = new LinuxButton; // ok but not ok!! (should result in
 an error in some way)

 Obviously I can cast and check the type and do all that. Just
 feels like the wrong way to go about it because it requires a lot
 of casting and polluting the code with checks that in general,
 should be unnecessary. Again: In the WindowsGui I want to use
 WindowsButton, not iButton because WindowsGui will never need any
 other type of button. iButton is too general to use in WindowsGui.

 (it would be cool if one could do something like

 class WindowsGui : iGui
      iButton <= WindowsButton // constrains iButton to always be a
 WindowsButton. Checks/casts are automatically added by compiler
 when necessary
 {
      // use WindowsButton here with proper covariance relations and
 checks/casts
 }

 Anyways, hopefully there is some single trick to get what I'm
 asking?
It should not work because the derived type is requiring more than the interface. iGui requires that the parameter to button() is iButton: property iButton button(ref iButton button); However, WindowsGui is bringing an extra requirement by asking a more specific iButton: property WindowsButton button(ref WindowsButton button) Note that there is no problem with the return type because this time the derived type is still returning an iButton because WindowsButton "is an" iButton. I don't know whether this works for you but I made the actual button a constructor parameter: interface iGui { property iButton button(); } class WindowsGui : iGui { WindowsButton _button; // The constructor gets the button this(WindowsButton button) { this._button = button; } property WindowsButton button() { return _button; } } interface iButton { } class WindowsButton : iButton { } void main() { auto w = new WindowsGui(new WindowsButton()); w.button; } Ali
Feb 21 2014
parent "Frustrated" <c1514843 drdrb.com> writes:
On Friday, 21 February 2014 at 23:19:19 UTC, Ali Çehreli wrote:
 On 02/21/2014 02:54 PM, Frustrated wrote:
 interface iGui
 {
      property iButton button(ref iButton button);
 }

 class WindowsGui : iGui
 {
     WindowsButton _button;

      property WindowsButton button(ref WindowsButton button)
     // property iButton button(ref iButton button)
     {
         _button = button;
         return button;
     }
 }

 interface iButton { }
 class WindowsButton : iButton { }


 Should this not work?

 Error: class main.WindowsGui interface function 'iButton
 button(ref iButton
 button)  property' is not implemented

 Or by using the commented line:

 Error: cannot implicitly convert expression (button) of type
 main.iButton to main.WindowsButton


 1. In the first case I override a property using a more derived
 type. This should work but doesn't. Seems D doens't support
 covariance properly?

 2. In the second case, I can cast to make everything work. This
 seems wrong. Hence goto 1. WindowsGui is designed to only work
 with WindowsButton, say, and I should never have to use iButton
 in the WindowsGui class unless, maybe, I want to support
 non-windows buttons in the WindowsGui for some reason.

 Basically, because of the covariance issue I end up having to 
 use
 a lot of casts. Hopefully theres some simple trick that won't
 pollute the code to make this work. I guess I could use a
 templated property with a generic type that is derivable from
 iButton to make it work?

 In some sense I can understand the error. If I'm using iGui 
 then
 I have the option to use any button(since it is generic) but if
 iGui is a WindowsGui I'm not allowing this. The issue is, that 
 I
 will have some type of dependency restrictions on the types.

 e.g.,

 iGui g = new WindowsGui;

 g.button = new LinuxButton; // ok but not ok!! (should result 
 in
 an error in some way)

 Obviously I can cast and check the type and do all that. Just
 feels like the wrong way to go about it because it requires a 
 lot
 of casting and polluting the code with checks that in general,
 should be unnecessary. Again: In the WindowsGui I want to use
 WindowsButton, not iButton because WindowsGui will never need 
 any
 other type of button. iButton is too general to use in 
 WindowsGui.

 (it would be cool if one could do something like

 class WindowsGui : iGui
     iButton <= WindowsButton // constrains iButton to always 
 be a
 WindowsButton. Checks/casts are automatically added by compiler
 when necessary
 {
     // use WindowsButton here with proper covariance relations 
 and
 checks/casts
 }

 Anyways, hopefully there is some single trick to get what I'm
 asking?
It should not work because the derived type is requiring more than the interface. iGui requires that the parameter to button() is iButton: property iButton button(ref iButton button); However, WindowsGui is bringing an extra requirement by asking a more specific iButton: property WindowsButton button(ref WindowsButton button) Note that there is no problem with the return type because this time the derived type is still returning an iButton because WindowsButton "is an" iButton. I don't know whether this works for you but I made the actual button a constructor parameter: interface iGui { property iButton button(); } class WindowsGui : iGui { WindowsButton _button; // The constructor gets the button this(WindowsButton button) { this._button = button; } property WindowsButton button() { return _button; } } interface iButton { } class WindowsButton : iButton { } void main() { auto w = new WindowsGui(new WindowsButton()); w.button; } Ali
But what about a setter? Using DI isn't the way to go here. The point that in the windows class, it will only ever use a windows button. This is fine, but because I'm using iGui(programming to interfaces), it causes a problem inside the windows class, which it shouldn't. e.g., if I only had one gui and used one class, then there would never be a problem. Also, it is not a problem of construct, I already have a solution by casting. But casting hides the fact that windowsgui is meant to use only a windows button... which is obvious in the design. Again iGui uses an iButton WindowsGui uses a WindowsButton But when iGui is an actual WindowsGui, it forces WindowsGui to be more generic than it is meant to be. The key piece of information here is that I will only ever use WindowsButtons with WindowsGui... this fact is not general and the reason the compiler throws the error BUT it is always the case in my code(except in errors). I need to inform the compiler that it is always the case and then I can do what I want.
Feb 21 2014
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 21 Feb 2014 17:54:06 -0500, Frustrated <c1514843 drdrb.com> wrote:

 interface iGui
 {
 	 property iButton button(ref iButton button);
 }

 class WindowsGui : iGui
 {
 	WindowsButton _button;

 	 property WindowsButton button(ref WindowsButton button)
 	// property iButton button(ref iButton button)
 	{
 		_button = button;
 		return button;
 	}
 }

 interface iButton { }
 class WindowsButton : iButton { }


 Should this not work?
What you are trying to do is not legal. e.g.: class RogueButton : iButton { } iGui gui = new WindowsGui; gui.button = new RogueButton; Note that setting gui.button to any iButton is legal, but the derived type REQUIRES a WindowsButton. This would have to be rejected at runtime, because the compile-time type is implicitly convertible. There are two types of variance that are logical, contravariance and covariance. covariance allows you to *return* a more derived type than the base. In other words, this would be legal (assume same iButton/WindowsButton structure): interface iGui { property iButton button(); } class WindowsGui : iGui { property WindowsButton button() {...}; } This works, because whenever you return a WindowsButton, you ALSO are returning an iButton. In fact, D supports this. The opposite is contravariance, and that's used on *input* parameters. In this case, the derived method can accept a base of the parameter that the base class defines: interface iGui { void button(WindowsButton); // please humor me, I know you don't want to do this :) } class WindowsGui : iGui { void button(iButton); } This is logically sound, because the actual implementation only requires an iButton. Therefore, passing a WindowsButton into the iGui interface still satisfies that requirement. However, D does NOT support contravariance.
 2. In the second case, I can cast to make everything work. This
 seems wrong. Hence goto 1. WindowsGui is designed to only work
 with WindowsButton, say, and I should never have to use iButton
 in the WindowsGui class unless, maybe, I want to support
 non-windows buttons in the WindowsGui for some reason.
This is actually the correct mechanism if you want to use polymorphism. However, in some cases, a templated system may be more advantageous than an interface system. One other possibility is to use overloading -- i.e.: class WindowsGui { property WindowsButton button(WindowsButton b) { return _button = b;} property WindowsButton button(iButton b) { if(auto wb = cast(WindowsButton)b) button = wb; else throw new ButtonException; } } This is not really an attractive solution, but it could be easily generated as a mixed-in solution. -Steve
Feb 21 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Saturday, 22 February 2014 at 01:03:22 UTC, Steven
Schveighoffer wrote:
 On Fri, 21 Feb 2014 17:54:06 -0500, Frustrated 
 <c1514843 drdrb.com> wrote:

 interface iGui
 {
 	 property iButton button(ref iButton button);
 }

 class WindowsGui : iGui
 {
 	WindowsButton _button;

 	 property WindowsButton button(ref WindowsButton button)
 	// property iButton button(ref iButton button)
 	{
 		_button = button;
 		return button;
 	}
 }

 interface iButton { }
 class WindowsButton : iButton { }


 Should this not work?
What you are trying to do is not legal. e.g.: class RogueButton : iButton { } iGui gui = new WindowsGui; gui.button = new RogueButton; Note that setting gui.button to any iButton is legal, but the derived type REQUIRES a WindowsButton. This would have to be rejected at runtime, because the compile-time type is implicitly convertible. There are two types of variance that are logical, contravariance and covariance. covariance allows you to *return* a more derived type than the base. In other words, this would be legal (assume same iButton/WindowsButton structure): interface iGui { property iButton button(); } class WindowsGui : iGui { property WindowsButton button() {...}; } This works, because whenever you return a WindowsButton, you ALSO are returning an iButton. In fact, D supports this. The opposite is contravariance, and that's used on *input* parameters. In this case, the derived method can accept a base of the parameter that the base class defines: interface iGui { void button(WindowsButton); // please humor me, I know you don't want to do this :) } class WindowsGui : iGui { void button(iButton); } This is logically sound, because the actual implementation only requires an iButton. Therefore, passing a WindowsButton into the iGui interface still satisfies that requirement. However, D does NOT support contravariance.
 2. In the second case, I can cast to make everything work. This
 seems wrong. Hence goto 1. WindowsGui is designed to only work
 with WindowsButton, say, and I should never have to use iButton
 in the WindowsGui class unless, maybe, I want to support
 non-windows buttons in the WindowsGui for some reason.
This is actually the correct mechanism if you want to use polymorphism. However, in some cases, a templated system may be more advantageous than an interface system. One other possibility is to use overloading -- i.e.: class WindowsGui { property WindowsButton button(WindowsButton b) { return _button = b;} property WindowsButton button(iButton b) { if(auto wb = cast(WindowsButton)b) button = wb; else throw new ButtonException; } } This is not really an attractive solution, but it could be easily generated as a mixed-in solution. -Steve
It is legal exactly because I will always guarantee that the proper button will be used. It is not logically legal as mentioned several times... no one needs to mention that. But it is legal within the context of the code. I'll never use a RogueButton so why force me to code for the chance I might? Again, WindowsGui only uses WindowsButton which is a iButton type. So why force me to always use iButton and cast it to WindowsButton? Why can't I relax the condition to use the base type? The only reason it is illegal is because I could use a RogueButton, BUT I WON'T! If I do, then it is an error. Basically, the point is, the compiler could enforce the above but make the code more readable. e.g., I do this: property WindowsButton button(WindowsButton b) { } The compiler turns this into property WindowsButton button(iButton _b) { if (is(_b : WindowsButton)) assert(0, "Rogue button used"); auto b = cast(WindowsButton)_b; } One is very clean, the other is not. If by chance I use the wrong button(a Rogue button) then it results in an error(hopefully user controlled). One allows me to program in a natural way while the other makes me jump through hoops which litters the code with a bunch of casts and checks which are only there in the odd event that I assign the wrong type(which, I'm not going to do on purpose). Again, the whole point of why it is illegal because you can pass a RogueButton... BUT I DON'T INTEND TO PASS THEM! If I could absolutely guarantee that I won't pass them then there should be no problem(no asserts). Since I can't guarantee it I have to litter my code with checks? The compiler could do this for me.
Feb 22 2014
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 22 Feb 2014 15:17:37 -0500, Frustrated <c1514843 drdrb.com> wrote:

 It is legal exactly because I will always guarantee that the
 proper button will be used.
Static typing says it's not legal. D does not do dynamic type checking upon calling virtual functions.
 It is not logically legal as mentioned several times... no one
 needs to mention that. But it is legal within the context of the
 code. I'll never use a RogueButton so why force me to code for
 the chance I might?
You may not be the only one using WindowsGui. You can't guarantee other code won't do it. In any case, the compiler cannot possibly know your intentions.
 Basically, the point is, the compiler could enforce the above but
 make the code more readable.

 e.g.,

 I do this:

  property WindowsButton button(WindowsButton b)
 {

 }

 The compiler turns this into

  property WindowsButton button(iButton _b)
 {
      if (is(_b : WindowsButton)) assert(0, "Rogue button used");
      auto b = cast(WindowsButton)_b;

 }
This solution is not as efficient as the one I outlined. If you have a WindowsGui object, no need to accept iButton when you require WindowsButton.
 One allows me to program in a natural way while the other makes
 me jump through hoops which litters the code with a bunch of
 casts and checks which are only there in the odd event that I
 assign the wrong type(which, I'm not going to do on purpose).
Sorry, if you want a dynamically typed language, use one. D is not that.
 Again, the whole point of why it is illegal because you can pass
 a RogueButton... BUT I DON'T INTEND TO PASS THEM! If I could
 absolutely guarantee that I won't pass them then there should be
 no problem(no asserts). Since I can't guarantee it I have to
 litter my code with checks? The compiler could do this for me.
You can't guarantee it. That is the point. The compiler could do the checks for you, but D is not dynamically typed. The best you can do is encapsulate the type checking code as a mixin. -Steve
Feb 22 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Sunday, 23 February 2014 at 01:37:08 UTC, Steven Schveighoffer
wrote:
 On Sat, 22 Feb 2014 15:17:37 -0500, Frustrated 
 <c1514843 drdrb.com> wrote:

 It is legal exactly because I will always guarantee that the
 proper button will be used.
Static typing says it's not legal. D does not do dynamic type checking upon calling virtual functions.
 It is not logically legal as mentioned several times... no one
 needs to mention that. But it is legal within the context of 
 the
 code. I'll never use a RogueButton so why force me to code for
 the chance I might?
You may not be the only one using WindowsGui. You can't guarantee other code won't do it. In any case, the compiler cannot possibly know your intentions.
 Basically, the point is, the compiler could enforce the above 
 but
 make the code more readable.

 e.g.,

 I do this:

  property WindowsButton button(WindowsButton b)
 {

 }

 The compiler turns this into

  property WindowsButton button(iButton _b)
 {
     if (is(_b : WindowsButton)) assert(0, "Rogue button used");
     auto b = cast(WindowsButton)_b;

 }
This solution is not as efficient as the one I outlined. If you have a WindowsGui object, no need to accept iButton when you require WindowsButton.
 One allows me to program in a natural way while the other makes
 me jump through hoops which litters the code with a bunch of
 casts and checks which are only there in the odd event that I
 assign the wrong type(which, I'm not going to do on purpose).
Sorry, if you want a dynamically typed language, use one. D is not that.
 Again, the whole point of why it is illegal because you can 
 pass
 a RogueButton... BUT I DON'T INTEND TO PASS THEM! If I could
 absolutely guarantee that I won't pass them then there should 
 be
 no problem(no asserts). Since I can't guarantee it I have to
 litter my code with checks? The compiler could do this for me.
You can't guarantee it. That is the point. The compiler could do the checks for you, but D is not dynamically typed. The best you can do is encapsulate the type checking code as a mixin. -Steve
It has nothing to do with being dynamically typed. We can't solve this problem until you get your head out of the gutter(the gutter being how D does things already. Can't make progress on something if you ever look beyond what it can do). This has to do with simply adding checks to enforce the type. I can guarantee it, but like you said, I can't guarantee what others do. Hence the check. The fact is, I presented two versions of the code. One represents the other. It is a representational problem, nothing more, nothing less. Please understand that from now on. e.g., a switch statement is just a representational form of if statements to simplify. I'll I'm talking about is adding a switch statement. (if you take that literal and can't see how it relates to the original problem then you are completely missing the point of the whole discussion) I did think it might be possible to use CT reflection to generate all the type checking automatically but this might be difficult and would have to generate a new class. It seems like the only way to get at this problem in D.
Feb 23 2014
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 23 Feb 2014 08:26:10 -0500, Frustrated <c1514843 drdrb.com> wrote:

 It has nothing to do with being dynamically typed. We can't solve
 this problem until you get your head out of the gutter(the gutter
 being how D does things already. Can't make progress on something
 if you ever look beyond what it can do).
You have a nasty habit of assuming people do not know as much as you. Bottom line, I get what you are asking, always have. It could be done, but D won't do it for you, nor will it be modified to do that. The costs of additional runtime type checks are far too great to implicitly add them. Use mixin generation, and be done with it. -Steve
Feb 23 2014
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/22/2014 12:17 PM, Frustrated wrote:

 Again, the whole point of why it is illegal because you can pass
 a RogueButton... BUT I DON'T INTEND TO PASS THEM!
Thinking that way, many rules of a statically type-checked language like D would be unnecessary. ;)
 WindowsGui only uses WindowsButton which is a iButton type.
WindowsGui is totally free to use any type it wants. However, it cannot both claim to implement an interface without actually obeying its requirements.
 Why can't I relax the condition to use the base type?
The users of iGui don't even know what a WindowsButton is: interface iGui { property iButton button(ref iButton button); } Imagine the following that I write: void foo(WindowsGui gui, iButton b) { gui.button(b); } Is the call legal or not? How would I know and why should I care? I have a WindowsGui, which happens to be an iGui and I have an iButton. According to the contract of the interface I should be able to call it without fear of type problems. Even, I can create my own iButton and pass it to that WindowsGui: gui.button(new MyButton()); I should be able to do all of that just because WindowsGui promises to be an iGui. Getting back to what I said above: WindowsGui is totally free to use any type it wants. That's why both Steven and I made it take its button as a constructor parameter. Then, you also mentioned a setter. That's fine too. As long as WindowsGui allows me to give it an iButton when I call button(), it is all fine. Ali
Feb 22 2014
prev sibling parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Saturday, 22 February 2014 at 20:17:37 UTC, Frustrated wrote:
 I do this:

  property WindowsButton button(WindowsButton b)
 {

 }

 The compiler turns this into

  property WindowsButton button(iButton _b)
 {
     if (is(_b : WindowsButton)) assert(0, "Rogue button used");
     auto b = cast(WindowsButton)_b;

 }
Why does your WindowsGui violate the iGui contract?
Feb 23 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Sunday, 23 February 2014 at 20:41:30 UTC, Jesse Phillips wrote:
 On Saturday, 22 February 2014 at 20:17:37 UTC, Frustrated wrote:
 I do this:

  property WindowsButton button(WindowsButton b)
 {

 }

 The compiler turns this into

  property WindowsButton button(iButton _b)
 {
    if (is(_b : WindowsButton)) assert(0, "Rogue button used");
    auto b = cast(WindowsButton)_b;

 }
Why does your WindowsGui violate the iGui contract?
It doesn't. It simply that one can't specify dependencies in D if (iGui is WindowsGui) then iButton is WindowsButton; It's not very hard logic but people are not even trying. I am attempting to make a mixin to solve the problem. The mixin will simply overload all methods in the derived class(WindowsGui) and when WindowsButton is used it will create an overload using iButton(to satisfy the interface) with the check to make sure the iButton is a WindowsButton. It will give me what I want except I have to create the mixin and then insert it in all the classes. (In theory though it should not add any overhead is used where it is not suppose to) But unfortunately when I try to find all members that use WindowsButton(or whatever) to be able to create the new overload, I get error due to the inner foreach. foreach (am; __traits(derivedMembers, B)) foreach (m; [__traits(getOverloads, B, am)]) { // check if method contains an parameter of type WindowsButton, then create identical method definition that uses iButton instead. Put a check in the method and call this method using a cast. This essentially overrides the virtual method satisfying the interface but passes the work to the user defined method. } What the above code will do, when working, is create the verbose code you quoted from the first case: property WindowsButton button(WindowsButton b) { } The ***mixin*** turns **ADDS** this property WindowsButton button(iButton _b) { if (is(_b : WindowsButton)) assert(0, "Rogue button used"); auto b = cast(WindowsButton)_b; button(b); // Call the user defined function here(hopefully) }
Feb 23 2014
parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Sunday, 23 February 2014 at 21:06:03 UTC, Frustrated wrote:
 Why does your WindowsGui violate the iGui contract?
It doesn't. It simply that one can't specify dependencies in D if (iGui is WindowsGui) then iButton is WindowsButton; It's not very hard logic but people are not even trying.
I understand what you intend your code to do, but that is still breaking the contract which you setup. iGui takes an iButton because you defined it that way, to only handle specific types of iButton is a breach of contract. The language lets you break contracts, but it should not help you do so.
Feb 23 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Sunday, 23 February 2014 at 23:14:24 UTC, Jesse Phillips wrote:
 On Sunday, 23 February 2014 at 21:06:03 UTC, Frustrated wrote:
 Why does your WindowsGui violate the iGui contract?
It doesn't. It simply that one can't specify dependencies in D if (iGui is WindowsGui) then iButton is WindowsButton; It's not very hard logic but people are not even trying.
I understand what you intend your code to do, but that is still breaking the contract which you setup. iGui takes an iButton because you defined it that way, to only handle specific types of iButton is a breach of contract. The language lets you break contracts, but it should not help you do so.
Nope. It has nothing to do with the contract. You are totally missing the point. It is all about reducing typing a bunch of extra shit. Don't know why you can't see that. In any case once I get the mixin in finish it will do what I want and be good enough. IF the damn language had the ability to specify dependencies then it wouldn't be a problem. Just because you insist on using D's current model as the only model you will always be right... I hope that makes you happy. In the mean time I'll be moving on to writing cleaner code...
Feb 23 2014
parent reply "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Sunday, 23 February 2014 at 23:23:07 UTC, Frustrated wrote:
 Nope. It has nothing to do with the contract. You are totally
 missing the point.
iGui has a function which takes any iButton. That is a defined contract of iGui, your denial does not change that.
Feb 23 2014
parent "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Monday, 24 February 2014 at 00:09:55 UTC, Jesse Phillips wrote:
 On Sunday, 23 February 2014 at 23:23:07 UTC, Frustrated wrote:
 Nope. It has nothing to do with the contract. You are totally
 missing the point.
iGui has a function which takes any iButton. That is a defined contract of iGui, your denial does not change that.
Let me put this another way. I started with the question of why you need to break the contract you define. In other words, "What is the problem you are trying to solve." But instead you insisted the "it must be solved this way" instead of giving details on what the problem actually is. D already provides a way to say that WindowsGui only takes WindowsButtons, you did so in your original code, just don't extend iGui since that isn't the contract you fulfill.
Feb 23 2014
prev sibling parent reply "Eric Suen" <eric.suen.tech gmail.com> writes:
Generic?

"Frustrated" <c1514843 drdrb.com> ...
 interface iGui
 {
  property iButton button(ref iButton button);
 }

 class WindowsGui : iGui
 {
 WindowsButton _button;

  property WindowsButton button(ref WindowsButton button)
 // property iButton button(ref iButton button)
 {
 _button = button;
 return button;
 }
 }

 interface iButton { }
 class WindowsButton : iButton { }


 Should this not work?

 Error: class main.WindowsGui interface function 'iButton
 button(ref iButton
 button)  property' is not implemented
 Or by using the commented line:

 Error: cannot implicitly convert expression (button) of type
 main.iButton to main.WindowsButton

 1. In the first case I override a property using a more derived
 type. This should work but doesn't. Seems D doens't support
 covariance properly?

 2. In the second case, I can cast to make everything work. This
 seems wrong. Hence goto 1. WindowsGui is designed to only work
 with WindowsButton, say, and I should never have to use iButton
 in the WindowsGui class unless, maybe, I want to support
 non-windows buttons in the WindowsGui for some reason.

 Basically, because of the covariance issue I end up having to use
 a lot of casts. Hopefully theres some simple trick that won't
 pollute the code to make this work. I guess I could use a
 templated property with a generic type that is derivable from
 iButton to make it work?

 In some sense I can understand the error. If I'm using iGui then
 I have the option to use any button(since it is generic) but if
 iGui is a WindowsGui I'm not allowing this. The issue is, that I
 will have some type of dependency restrictions on the types.

 e.g.,

 iGui g = new WindowsGui;

 g.button = new LinuxButton; // ok but not ok!! (should result in
 an error in some way)

 Obviously I can cast and check the type and do all that. Just
 feels like the wrong way to go about it because it requires a lot
 of casting and polluting the code with checks that in general,
 should be unnecessary. Again: In the WindowsGui I want to use
 WindowsButton, not iButton because WindowsGui will never need any
 other type of button. iButton is too general to use in WindowsGui.

 (it would be cool if one could do something like

 class WindowsGui : iGui
     iButton <= WindowsButton // constrains iButton to always be a
 WindowsButton. Checks/casts are automatically added by compiler
 when necessary
 {
     // use WindowsButton here with proper covariance relations and
 checks/casts
 }

 Anyways, hopefully there is some single trick to get what I'm
 asking? 
Feb 21 2014
parent reply "Frustrated" <c1514843 drdrb.com> writes:
On Saturday, 22 February 2014 at 05:20:25 UTC, Eric Suen wrote:
 Generic?
I don't see how this would help. I'd have to specify every concrete type in the creation of the object which might be significant. I can't use a generic virtual method so that doesn't help either. It would be nice to have something like T foo(T : iButton)(T button); Which then I override with WindowsButton foo(WindowsButton button) { } Since WindowsButton is derived from iButton. The compiler would have to insert a type check to make sure when I called the first one(from the interface) that it was a windows button that was passed(since any iButton could be passed) when using the WindowsGui. The main point of all this is simply efficiency. I have to liter the code with checks and casts when it is entirely possible to get the compiler to automate it all. By doing so one can program the concrete class in a much more natural way.
Feb 22 2014
parent "Eric Suen" <eric.suen.tech gmail.com> writes:
interface iButton { }

class WindowsButton : iButton { }

interface iGui(T)
{
 property T button(ref T button);
}

class WindowsGui : iGui!(WindowsButton)
{
  property WindowsButton button(ref WindowsButton button) {
  return button;
 }
}

"Frustrated" <c1514843 drdrb.com>
 On Saturday, 22 February 2014 at 05:20:25 UTC, Eric Suen wrote:
 Generic?
I don't see how this would help. I'd have to specify every concrete type in the creation of the object which might be significant. I can't use a generic virtual method so that doesn't help either. It would be nice to have something like T foo(T : iButton)(T button); Which then I override with WindowsButton foo(WindowsButton button) { } Since WindowsButton is derived from iButton. The compiler would have to insert a type check to make sure when I called the first one(from the interface) that it was a windows button that was passed(since any iButton could be passed) when using the WindowsGui. The main point of all this is simply efficiency. I have to liter the code with checks and casts when it is entirely possible to get the compiler to automate it all. By doing so one can program the concrete class in a much more natural way.
Feb 22 2014