尝试从接口调用方法会导致错误"需要对象引用"

时间:2015-09-10 20:29:03

标签: c#

This article PS6的代码中有错误... xyz()产生错误:

  

非静态方法需要Object引用。

class Demo : abc
{
    public static void Main()
    {
        System.Console.WriteLine("Hello Interfaces");
        xyz();

    }

    public void xyz()
    {
        System.Console.WriteLine("In xyz");
    }
}

interface abc
{
    void xyz();
}

你能解释一下我的xyz()调用是什么方法,属性,字段。我迷失了真正被称之为的东西?

为什么这不起作用?当我们制作Demo的新实例时?

这确实......

Demo obj = new Demo();
obj.xyz();

3 个答案:

答案 0 :(得分:2)

  

你能解释一下我的xyz()调用是什么方法,属性,字段。

这是Method

  

为什么这不起作用?

因为xyz()未定义为static且不能为static,因为修饰符static对接口成员声明无效。所以你应该创建这样的实例:

Demo obj = new Demo();
obj.xyz();

<强> 修改

  

为什么我们要使用界面?

使用界面不仅可以保证标准化灵活性可扩展性可扩展性可维护性< / em>,可重用性可测试性 power ,但也是在C#中使用接口的主要原因之一是因为C#{{3} }。

答案 1 :(得分:2)

public void xyz()
{
    System.Console.WriteLine("In xyz");
}
  • public表示它是一个公共方法,其他类可以进行交互 用它。
  • void表示它返回void a.k.a. nothing
  • xyz是这个名字 方法
  • ()是参数的位置,但是这里没有调用方法的参数,因此它是空的
  • 卷曲括号之间的
  • 是代码块,也称为函数或方法体

主要方法被标记为类似c语言,代码执行开始,所以你应该从那里开始。

答案 2 :(得分:0)

xyz是一种方法。一个实例方法要精确,所以让我试着解释为什么你不能从静态方法Main调用它,以及如何解决它。

类定义定义了哪些方法(和属性等)。如果你创建它的实例(new Demo),你就有了一个对象。对象引用类,因此您知道它包含哪些功能,并且它拥有自己的数据块,您可以在其中存储值,因此10个实例可以包含10个不同的值。

例如:

class Demo {
  public string name;
}

var a = new Demo();
a.name = 'John';
var b = new Demo();
b.name = 'Bob';
// At this point, a.name is still John. a and b each have their own name.

普通方法是实例方法。它可以到达并使用那些实例变量。因此,扩展前面的示例,您可以这样做:

class Demo {
  public string name;
  public void WhoAmI() {
    System.Console.WriteLine(this.name);
  }
}

var a = new Demo();
a.name = 'John';
var b = new Demo();
b.name = 'Bob';
a.WhoAmI(); // outputs 'John'

现在,除了那些实例变量和实例方法之外,还有静态成员(成员是变量,方法,属性......)。 static意味着它们不属于实例,而是属于类定义。应用程序中只有一个。他们属于阶级而不是实例。

现在,对象实例知道它属于哪个类。如果您创建变量var a = new Demo(),那么a知道它是Demo,因此您可以通过它或通过它调用示例中的Main之类的静态方法。

但是,在静态方法中,如果不知道它所属的实例。毕竟,甚至不需要成为一个实例。您可以拨打a.Main(),但也可以拨打Demo.Main()。 因此,您不能使用实例变量,也不能使用调用实例方法。由于xyz是一个实例方法,因此无法从静态方法Main调用它。

现在解决方法可能是xyz静态。毕竟,它不会引用其他实例成员。但是,接口不允许这样做,所以这会引发另一个错误。接口描述实例的外观,不支持静态成员。这是C#中的设计决策。

所以,或者,你可以引入一个额外的静态实现,并从接口方法调用它。这样,接口实现仍然可以调用静态版本,Main方法也是如此:

class Demo : abc
{
    public static void Main()
    {
        System.Console.WriteLine("Hello Interfaces");
        zyx();
    }

    public static void zyx() {
      System.Console.WriteLine("In zyx");
    }

    public void xyz()
    {
        zyx();
    }
}

interface abc
{
    void xyz();
}

关于界面。是在评论中看到你问这个。接口有很多用途,尽管它们的解释有点超出范围。但请注意,每个类都不会需要接口。因此,如果您的特定实现中不需要接口,则不需要我引入的额外方法。 CodeProject使您实现接口的原因是因为它是本教程的主题。 ;)

他们在介绍他们的教程时简要总结了界面的优势:

  

C#中的接口提供了一种实现运行时多态性的方法。运用   我们可以通过接口调用来自不同类的函数   相同的接口参考,而我们可以使用虚函数   从同一继承中的不同类调用函数   层次结构通过相同的参考

所以,如果你有不同类型的Demo类,你可以将它们相互扩展:

class BaseDemo {
  abstract void xyz() {
    System.Console.WriteLine("in Basedemo.xyz");
  }
}

class SpecificDemo1: BaseDemo {
  override void xyz() {
    System.Console.WriteLine("in SpecificDemo1.xyz");
  }
}

class SpecificDemo2: BaseDemo {
  override void xyz() {
    System.Console.WriteLine("in SpecificDemo2.xyz");
  }
}

现在,您可以声明一个这样的方法:

class DemoUser {
  static void CallXyz(BaseDemo d) {
    d.xyz();
  }
}

var a = new SpecificDemo2();
DemoUser.CallXyz(a);

CallXyz接受SpecificDemo1和SpecificDemo2类型的变量。这样做的原因是它的参数声明为BaseDemo类型,因此它接受BaseDemo的所有后代的实例。

然而,制作大型的层次结构来支持这一点,只是没有用和可维护,所以这就是接口的用武之地。你可以在界面中捕获一小部分功能,然后使用它。

例如,在下面的代码中,我在接口中声明了两个功能,Foo和Bar。三个类实现这些接口中的一个或多个。这些课本身并不相关。它们可以,但从界面的角度来看并不重要。

class Foo: IFoo {
  public void DoFoo() {
    System.Console.WriteLine('Foo is fooing');
  }
}
class Bar: IBar {
  public void DoBar() {
    System.Console.WriteLine('Bar is barring');
  }
}

class FooBar: IFoo, IBar {
  public void DoFoo() {
    System.Console.WriteLine('FooBar is fooing');
  }
  public void DoBar() {
    System.Console.WriteLine('FooBar is barring');
  }
}

IFoo {
  void DoFoo() {
}
IBar {
  void DoBar() {
}

现在,如果有一种想要'Bar'的方法,它可以接受一个I​​Bar参数。这种方法接受Bar和Foobar的实例。

通过正常继承,这是不可能实现的。您必须从Foo和Bar继承FooBar,这是不可能的,或者您必须使FooBar成为基类,在这种情况下,您必须已经在基类中声明这两个方法。这也意味着Foo实例可以作为Bar传递,反之亦然。这是不可取的。

使用接口,您可以简单地声明一个小功能,并在您喜欢的任何类中实现它。