C# “C”;继承;静态方法?
下面是我想要完成的一个例子:C# “C”;继承;静态方法?,c#,inheritance,static-methods,C#,Inheritance,Static Methods,下面是我想要完成的一个例子: abstract class DoSomething { static void DoWhateverItIsThatIDo() { Console.WriteLine("You asked the abstract class to work. Too bad."); } } class InspireMe : DoSomething { static void DoWhateverItIsThatIDo()
abstract class DoSomething
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe : DoSomething
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe : DoSomething
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You aren't worth it.");
}
}
class Program
{
static void Main()
{
DoSomething worker = InsultMe;
worker.DoWhateverItIsThatIDo();
worker = InspireMe;
worker.DoWhateverItIsThatIDo();
}
}
我来自Python的背景,方法本身可以是变量,然后可以调用它。看起来C#没有这个概念,但我正试图实现类似的目标
这个想法是我想要一个抽象类型的变量,这样许多不同类型的子类型可以存在其中。所有这些子类型都有特定的方法。我希望能够将这些子类型中的任何一个分配给这个抽象类型的变量,然后调用子类型中存在的静态方法
在C#术语中,我希望能够将类分配给变量,而不是类的实例,然后调用该类的静态方法
工厂听起来可能是在正确的路径上,但我不确定工厂本身如何能够生成对类的这些引用(而不是创建实例)
我可以修改它以使用实例,但是假设我想要生成每种类型的类的静态方法,所有这些类仍然从基类型继承
我觉得很有可能有一种方法可以做到这一点——有人能给我一个建议吗?在C中,你不能用类作为变量,正如你所描述的那样。反射本质上允许您将类型视为变量,并动态地调用它们的静态成员,但这将是混乱的,并且不是类型安全的 通过使用singleton模式,您基本上可以完成您想要做的事情:
interface IDoSomething
{
void DoWhateverItIsThatIDo();
}
class DoSomething : IDoSomething
{
private DoSomething() {}
internal static readonly IDoSomething Instance;
static DoSomething()
{
Instance = new DoSomething();
}
public void DoWhateverItIsThatIDo()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe : IDoSomething
{
private InspireMe() {}
internal static readonly IDoSomething Instance;
static InspireMe()
{
Instance = new InspireMe();
}
public void DoWhateverItIsThatIDo()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe : IDoSomething
{
private InsultMe() {}
internal static readonly IDoSomething Instance;
static InsultMe()
{
Instance = new InsultMe();
}
public void DoWhateverItIsThatIDo()
{
Console.WriteLine("You aren't worth it.");
}
}
C#和Java都不能让您重写静态基类方法
但是,您似乎正在使用对对象的引用(您的worker
变量),所以为什么不使用非静态类方法呢
(如果这不是你想要做的,请澄清。)我不是100%确定这是你想要的,但我写了一个模拟的库
当然,这需要大量使用
dynamic
关键字,这可能没有什么用处,因为您会丢失大量编译时检查。除了类和实例之外,您真正想要的是对具有特定签名的方法的引用,在您的例子中是void()
虽然不能将静态类分配给变量,但可以以类型安全的方式将方法分配给变量。在C#中,通常会使用or重载,具体取决于方法签名的外观
为了使这一点更有趣,假设您想要引用类似于intfoo(string,bool)
的内容,只需使用Func
类型的变量,并将具有此签名的任何方法分配给它即可
解决问题的代码大致如下所示:
class DoSomething
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You aren't worth it.");
}
}
class Program
{
static void Main()
{
Action worker = InsultMe.DoWhateverItIsThatIDo;
worker();
worker = InspireMe.DoWhateverItIsThatIDo;
worker();
}
}
解决方法可能是在基本抽象类中声明类型为
Action
的属性,该属性保存要调用的方法。然后在派生类实例化期间通过调用基类构造函数初始化此属性:
abstract class DoSomething
{
public Action DoWhateverItIsThatIDo { get; set; }
protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }
protected DoSomething(Action whatAction)
{
DoWhateverItIsThatIDo = whatAction;
}
protected static void DoIt()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe : DoSomething
{
public InspireMe() : base(InspireMe.DoIt) { }
private static void DoIt()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe : DoSomething
{
public InsultMe() : base(InsultMe.DoIt) { }
private static void DoIt()
{
Console.WriteLine("You aren't worth it.");
}
}
class DoWhatBaseClassDoes : DoSomething
{
public DoWhatBaseClassDoes() : base() {}
}
class Program
{
static void Main(string[] args)
{
DoSomething worker = new InsultMe();
worker.DoWhateverItIsThatIDo();
worker = new InspireMe();
worker.DoWhateverItIsThatIDo();
// In this case base class method is invoked
worker = new DoWhatBaseClassDoes();
worker.DoWhateverItIsThatIDo();
}
}
从某种意义上说,一个方法可以是一个变量:
Action workerMethod=InspireMe.DoWhateverItIsThatIDo;工作方法()代码>?不完全是你写的,但是如果你想要一个实际的工作者对象,你可以调用多个方法,那么你不应该使用静态方法;派生类型没有要调用的基类型的构造函数(唯一的构造函数是私有的),因此不会编译。如果您确实向它们公开了一个构造函数,那么类型就不会是单例的,因为您创建了多个类型实例和所有实例。@Servy我在示例中没有看到任何派生类,只是接口实现,因此没有编译问题。@Servy很抱歉,您不得不批评我的半生不熟的代码。我现在已经验证了它的编译和工作符合预期。我认为没有任何理由使用单例或静态代码。静态代码无论如何都不适合生成。没有注射就无法测试。他似乎不懂c#IMO。。。因为所需要的只是接口,最多是一个带有虚方法的抽象类。@phillip似乎OP需要一些适合某个接口的静态对象。对于单例模式来说,这不是一个很好的用例吗?代码的静态部分实际上做的不多。只需调用一个空构造函数并将其分配给一个字段。你们可以得到我的投票,但问题是。。。我以为他想要DoSomething.DoWhateverItIsThatIDo()作为默认方法,如果它不存在于InspireMe或Imprime中就会被调用。。。也许我错了-我们会明白的。不编译-侮辱我
和InspireMe
是类型,而不是Action
s-这应该是Action worker=侮辱我代码>然后worker()代码>。您可能还需要向这些静态方法添加一个public
修饰符谢谢Pieter,修好了这是个不错的密码员。。。感觉非常javascript(ish)…:这看起来比应该的麻烦多了,但我想它完成了任务+1.
class DoSomething
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe
{
static void DoWhateverItIsThatIDo()
{
Console.WriteLine("You aren't worth it.");
}
}
class Program
{
static void Main()
{
Action worker = InsultMe.DoWhateverItIsThatIDo;
worker();
worker = InspireMe.DoWhateverItIsThatIDo;
worker();
}
}
abstract class DoSomething
{
public Action DoWhateverItIsThatIDo { get; set; }
protected DoSomething() { DoWhateverItIsThatIDo = DoSomething.DoIt; }
protected DoSomething(Action whatAction)
{
DoWhateverItIsThatIDo = whatAction;
}
protected static void DoIt()
{
Console.WriteLine("You asked the abstract class to work. Too bad.");
}
}
class InspireMe : DoSomething
{
public InspireMe() : base(InspireMe.DoIt) { }
private static void DoIt()
{
Console.WriteLine("You are amazing.");
}
}
class InsultMe : DoSomething
{
public InsultMe() : base(InsultMe.DoIt) { }
private static void DoIt()
{
Console.WriteLine("You aren't worth it.");
}
}
class DoWhatBaseClassDoes : DoSomething
{
public DoWhatBaseClassDoes() : base() {}
}
class Program
{
static void Main(string[] args)
{
DoSomething worker = new InsultMe();
worker.DoWhateverItIsThatIDo();
worker = new InspireMe();
worker.DoWhateverItIsThatIDo();
// In this case base class method is invoked
worker = new DoWhatBaseClassDoes();
worker.DoWhateverItIsThatIDo();
}
}