Cannot implicitly convert derived type

Frustrated c1514843 at drdrb.com
Fri Feb 21 16:02:57 PST 2014


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.




More information about the Digitalmars-d-learn mailing list