Cannot implicitly convert derived type

Ali Çehreli acehreli at yahoo.com
Fri Feb 21 15:19:18 PST 2014


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



More information about the Digitalmars-d-learn mailing list