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'
现在,除了那些实例变量和实例方法,你也得到了静态成员(成员变量,方法,属性...)。静态意味着它们不属于实例,而是属于类定义。在应用程序中只有一个。他们属于班级而不是实例。
现在,对象实例知道它属于哪个类。如果你创建一个变量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让你实现一个接口的原因是因为它是本教程的主题。 ;)
他们简要介绍他们的教程总结了优势的接口:
Interfaces in C# provide a way to achieve runtime polymorphism. Using interfaces we can invoke functions from different classes through the same Interface reference, whereas using virtual functions we can invoke functions from different classes in the same inheritance hierarchy through the same reference
所以,如果你将有各种不同演示类的,你可以从彼此延伸他们:
现在
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和酒吧,在接口。三个类实现一个或多个这些接口。这些类本身并不相关。他们可以是,但从界面的角度来看并不重要。
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() {
}
现在,如果存在要“酒吧”的东西的方法,它可以接受的IBAR参数。这种方法接受Bar和Foobar的实例。
与正常的继承,这将无法实现。你必须从Foo和Bar继承FooBar,这是不可能的,否则你必须将FooBar作为基类,在这种情况下,你必须在基类中声明两个方法。这也意味着Foo实例可以作为Bar传递,反之亦然。这是不可取的。
使用接口,您可以简单地声明一个小功能,并在任意类中实现它。
第一部分是一种方法。在开始一个关于接口的特定教程之前,首先了解类和其他基本的C#东西是个好主意。问题的其余部分有点模糊(r)。我不清楚什么是有效的,什么是不行的,以及它不起作用。你有什么错误吗?如果是这样,请将它们添加到您的问题。 – GolezTrol
谢谢@GolezTrol我没有忘记它在问题中给我的错误。我一直在努力通过更详细地学习OOP来构建更好的应用程序,我认为我对类有一个好的概念,但其中的很多内容仅仅是一个难以理解的东西,因为这让我很困惑,为什么一个人会想要一个接口来封装他们在使用接口的方法中公开的内容。 – RiePwe