我正在将一些Java代码转换为C#,偶然发现了以下奇怪的事情:
public interface IActivation {
public abstract double func(double inputput);
public static class S1 : IActivation {
public double func(double input) {
if (input > 0) return 1.0;
return 0.0;
}
}
}
SomewhereElse(用法):
protected IActivation activation = new IActivation.S1();
查看原始代码,很清楚这是什么意思:
new IActivation.S1();
表明S1是IActivation的特定实现。)有趣的是,C#并不喜欢定义整个事物的方式:“无法创建静态类'IActivation.S1 的实例”。有没有人知道如何重构该代码以便保留1.和2.?
答案 0 :(得分:11)
在Java中,static
内部类对其封闭类型的成员没有隐式访问权限。在C#中,所有嵌套类型都没有对其父类型成员的访问权限;您无需在C#中添加任何修饰符来触发此行为。
在C#中,static
类是abstract sealed
,因此无法创建或派生它们 - 这与Java中的含义不同。另外,接口不能包含它们自己的类型声明。
尝试这样的事情:
public interface IActivation {
double Func(double inputput);
}
public class S1 : IActivation {
public static readonly S1 Instance = new S1();
private S1() { }
public double Func(double input) {
if (input > 0) return 1.0;
return 0.0;
}
}
如果您的目标是以某种“可读”的方式提供默认实现(尽管我认为IActivator.S1()
本质上更具可读性......),那么您可以创建一个静态工厂类:
public static class Activator
{
public static S1 S1
{
get
{
return S1.Instance;
// Or you could do this if you make the S1 constructor public:
// return new S1();
}
}
}
但是,我对这一说法更具可读性或更有帮助的说法提出质疑。当在特定类型的上下文中构造对象时,Visual Studio将显示该类型的所有子类型。所以如果你这样做(|
代表光标):
IActivator foo = new |
您应该获得当前范围中实现IActivotor的所有类的简洁列表。
答案 1 :(得分:6)
请勿将您的课程标记为static
。
答案 2 :(得分:2)
错误消息本身很清楚,S1类不能是静态的,因为您正在创建它的实例。从S1中删除static关键字。此外,访问修饰符和抽象修饰符在接口声明中无效。
在C#中,接口不能声明内部类型。
我的建议是使用Factory模式来获取正确的实例而不是接口中的嵌套类型(这会增加耦合/依赖关系)。
interface IActivation
{
double func(double inputput);
}
public static class ActivationFactory
{
IActivation GetImplA()
{
return new ImplA();
}
IActivation GetImplB()
{
return new ImplB();
}
}
class ImplA : IActivation { }
class ImplB : IActivation { }
答案 3 :(得分:2)
如果IActivation
不必是接口,则可以将其转换为抽象类
public abstract class IActivation
{
public abstract double func(double inputput);
public class S1 : IActivation
{
public override double func(double input)
{
if (input > 0) return 1.0;
return 0.0;
}
}
}
这改变了代码的实际含义,但允许你说
var s1 = new IActivation.S1();
更新我能想到的主要问题是,如果你有一个扩展别的东西并实现这个接口的类它将无法工作(你不能从两个类继承)。然后,您可以创建一个接口和一个实现抽象类的抽象类,但这有点傻。
另一种选择是
public interface IActivation {
// ...
}
public class Activation {
public class S1 : IActivation {
// ...
}
}
优点是您将IActivation保留为接口,但是您有另一个类乱丢您的命名空间。
在这两种情况下,你都没有从Java那里做过直接端口。
答案 4 :(得分:0)
使用sigleton模式为每个S'i'实现和撕裂appart接口和实现如上所述cdhowie
看来你不需要工厂 - 除非你的S'i'实例有自己的状态?