Interface not working as expected

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I'm declaring an interface (or two), but getting a compile-time error...

│ public abstract class Args
│ {
│ }

(I've also tried it as an interface, with the same result.)

│
│ public class MyArgs : Args
│ {
│ string Args1 = "Args 1" ;
│ }
│
│
│ public interface IArguable
│ {
│ void Argue ( Args args ) ;
│ }
│
│ public class Argument : IArguable
│ {
│ private string arg1 ;
│
│ public void Argue ( MyArgs args )
│ {
│ this.arg1 = args.Args1 ;
│ }
│ }

Yields:
ct.cs(30,18): error CS0535: 'Template.Argument' does not implement interface
member 'Template.IArguable.Argue(Template.Args)'

I thought it would be OK because MyArgs IS_A Args. I can change it to:

│ public void Argue ( Args args )
│ {
│ this.arg1 = ((MyArgs) args).Args1 ;
│ }

But I don't think I should need to. Is there something I'm missing? Is this
a limitation of interfaces? Is it a bug? (I see the same behaviour in the V2
beta.)
 
PIEBALD said:
I'm declaring an interface (or two), but getting a compile-time
error...

│ public abstract class Args
│ {
│ }

(I've also tried it as an interface, with the same result.)

│
│ public class MyArgs : Args
│ {
│ string Args1 = "Args 1" ;
│ }
│
│
│ public interface IArguable
│ {
│ void Argue ( Args args ) ;
│ }
│
│ public class Argument : IArguable
│ {
│ private string arg1 ;
│
│ public void Argue ( MyArgs args )
│ {
│ this.arg1 = args.Args1 ;
│ }
│ }

Yields:
ct.cs(30,18): error CS0535: 'Template.Argument' does not implement
interface member 'Template.IArguable.Argue(Template.Args)'

I thought it would be OK because MyArgs IS_A Args. I can change it to:

│ public void Argue ( Args args )
│ {
│ this.arg1 = ((MyArgs) args).Args1 ;
│ }

But I don't think I should need to. Is there something I'm missing?
Is this a limitation of interfaces? Is it a bug? (I see the same
behaviour in the V2 beta.)

That's not a limitation. You cannot implement an interface without
exactly matching the interface's method signatures.

Let's give your example some more meaninful names:

public class Food { }

public class Hotdog : Food { }


public interface Mamal
{
public void Eat(Food food);
}

public class Human : Mamal
{
public void Eat(Hotdog food) { }
}

Mamal prescribes that all objects of its kind can Eat() Food. Thus,
these Humans must be able to eat Food other than Hotdogs as well...

Cheers,
 
This is by design. It is neither a limitation nor a bug. You must
implement interface methods exactly as they are declared. It wouldn't
make sense to allow an interface method to be implemented with
subclassed parameters anyway. If it were allowed then there would be
no guarentee that the object could be used ubiquitously and
interchangeably. Afterall, how would you determine which objects need
to have the base class passed as a parameter and which ones need the
subclass?

Brian
 
Hmm... so an interface specifies that an instance must be able to Eat _any_
kind of Food, not just _some_ kind of food.

I'm not sure I like that. I can work around it with:

public class Human : Mamal
{
public void Eat(Food food) { Throw (Up) ; }
public void Eat(Hotdog food) { burp(); }
}

But I don't like the needless code. What I've done so far is.

public void Eat(Food food)
{
Hotdog meal ;
try
{
meal = (Hotdog) food ;
}
catch ( System.InvalidCastException )
{
throw ( Up) ;
}
}

But again, needless code, I'd rather get a compile-time error saying that
although tofu is a Food, it is not a Hotdog.

Might an abstract class help here? I'll try that.
 
Ah, generics. Generics is what I need. Works fine compiled with the beta.

namespace Template
{
public interface IArguable <Args>
{
void Argue ( Args args ) ;
}


public class MyArgs
{
public string Args1 = "Args 1" ;
}

public class Argument : IArguable <MyArgs>
{
public string arg1 ;

public void Argue ( MyArgs args )
{
this.arg1 = args.Args1 ;
}
}

class Template
{
[System.STAThread]
static void Main(string[] args)
{
Argument a = new Argument() ;
a.Argue ( new MyArgs() ) ;

return ;
}
}
}
 
Back
Top