C# "Inheriting" 静态方法?
C# "Inheriting" 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()
{
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# 没有这个概念,但我正在尝试完成类似的事情。
我的想法是我想要一个可以是抽象类型的变量,以便其中可以存在许多不同种类的子类型。所有这些子类型都有特定的方法。我希望能够将这些子类型中的任何一个分配给抽象类型的这个变量,然后调用子类型中存在的 static 方法。
在 C# 术语中,我希望能够将 class 分配给变量,而不是 实例 class,然后调用 class 的静态方法。
工厂听起来可能在正确的道路上,但我不确定工厂本身如何能够生成对 class(而不是创建实例)。
我可以修改它以使用实例,但假设我想要生成每种类型的 classes 的静态方法,所有这些仍然继承自基本类型。
我觉得最有可能做到这一点 - 有人能给我建议吗?
在您所描述的意义上,您不能在 C# 中使用 class 作为变量。反射本质上允许您将类型视为变量并动态调用它们的静态成员,但它会很混乱并且不安全。
你基本上可以通过使用单例模式来完成你想做的事情:
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.");
}
}
class Program
{
static void Main()
{
IDoSomething worker = InsultMe.Instance;
worker.DoWhateverItIsThatIDo();
worker = InspireMe.Instance;
worker.DoWhateverItIsThatIDo();
}
}
C# 和 Java 都不能让您覆盖静态基 class 方法。
但是,您似乎正在使用对对象的引用(您的 worker
变量),那么为什么不使用非静态 class 方法呢?
(如果这不是您的本意,请澄清。)
我不是 100% 确定这就是您想要的,但我写了一个模拟 Prototypal inheritance in C#.
的库
public class Foo: ProtoObject {}
public class Bar: Foo {}
dynamic myFoo = new Foo();
dynamic yourFoo = new Foo();
dynamic myBar = new Bar();
myFoo.Prototype.Name = "Josh";
myFoo.Prototype.SayHello = new Action(s => Console.WriteLine("Hello, " + s));
yourFoo.SayHello(myBar.Name); // 'Hello, Josh'
这当然涉及大量使用 dynamic
关键字,这可能没有用,因为你失去了很多编译时检查。
类 除了实例之外,您真正想要的是对具有特定签名的方法的引用,在您的情况下 void ()
.
虽然不能将静态 class 分配给变量,但可以以类型安全的方式将方法分配给变量。在 C# 中,您通常会使用 Action
or Func
的重载,具体取决于方法签名的外观。
为了让它更有趣一点,假设您想要引用类似 int Foo(string, bool)
的内容,只需使用 Func<string,bool,int>
类型的变量并将具有此签名的任何方法分配给它。
解决您的问题的代码大致如下所示:
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();
}
}
一种变通方法可能是在基本抽象 class 中声明类型 Action
的 属性,它包含要调用的方法。然后在派生 classes 实例化期间初始化此 属性,方法是调用基 class 构造函数:
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();
}
}
这是我想要完成的示例:
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# 没有这个概念,但我正在尝试完成类似的事情。
我的想法是我想要一个可以是抽象类型的变量,以便其中可以存在许多不同种类的子类型。所有这些子类型都有特定的方法。我希望能够将这些子类型中的任何一个分配给抽象类型的这个变量,然后调用子类型中存在的 static 方法。
在 C# 术语中,我希望能够将 class 分配给变量,而不是 实例 class,然后调用 class 的静态方法。
工厂听起来可能在正确的道路上,但我不确定工厂本身如何能够生成对 class(而不是创建实例)。
我可以修改它以使用实例,但假设我想要生成每种类型的 classes 的静态方法,所有这些仍然继承自基本类型。
我觉得最有可能做到这一点 - 有人能给我建议吗?
在您所描述的意义上,您不能在 C# 中使用 class 作为变量。反射本质上允许您将类型视为变量并动态调用它们的静态成员,但它会很混乱并且不安全。
你基本上可以通过使用单例模式来完成你想做的事情:
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.");
}
}
class Program
{
static void Main()
{
IDoSomething worker = InsultMe.Instance;
worker.DoWhateverItIsThatIDo();
worker = InspireMe.Instance;
worker.DoWhateverItIsThatIDo();
}
}
C# 和 Java 都不能让您覆盖静态基 class 方法。
但是,您似乎正在使用对对象的引用(您的 worker
变量),那么为什么不使用非静态 class 方法呢?
(如果这不是您的本意,请澄清。)
我不是 100% 确定这就是您想要的,但我写了一个模拟 Prototypal inheritance in C#.
的库public class Foo: ProtoObject {}
public class Bar: Foo {}
dynamic myFoo = new Foo();
dynamic yourFoo = new Foo();
dynamic myBar = new Bar();
myFoo.Prototype.Name = "Josh";
myFoo.Prototype.SayHello = new Action(s => Console.WriteLine("Hello, " + s));
yourFoo.SayHello(myBar.Name); // 'Hello, Josh'
这当然涉及大量使用 dynamic
关键字,这可能没有用,因为你失去了很多编译时检查。
类 除了实例之外,您真正想要的是对具有特定签名的方法的引用,在您的情况下 void ()
.
虽然不能将静态 class 分配给变量,但可以以类型安全的方式将方法分配给变量。在 C# 中,您通常会使用 Action
or Func
的重载,具体取决于方法签名的外观。
为了让它更有趣一点,假设您想要引用类似 int Foo(string, bool)
的内容,只需使用 Func<string,bool,int>
类型的变量并将具有此签名的任何方法分配给它。
解决您的问题的代码大致如下所示:
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();
}
}
一种变通方法可能是在基本抽象 class 中声明类型 Action
的 属性,它包含要调用的方法。然后在派生 classes 实例化期间初始化此 属性,方法是调用基 class 构造函数:
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();
}
}