例如,我有以下课程:
1。
class MyClass1
{
public MyClass1 Method()
{
...
return new MyClass1();
}
}
class MyClass2
{
public MyClass2 Method()
{
...
return new MyClass2();
}
}
这些方法具有相同的主体,这就是为什么我要提取代码并重复使用。
2。
abstract class MyClass
{
protected void Method()
{
...
}
}
class MyClass1 : MyClass
{
public MyClass1 Method()
{
base.Method();
return new MyClass1();
}
}
class MyClass2 : MyClass
{
public MyClass2 Method()
{
base.Method();
return new MyClass2();
}
}
但是,由于存在许多此类方法,因此最好将这些方法移至基类MyClass
中>
3。
abstract class MyClass<T>: where T : MyClass<T>
{
protected abstract T Create();
public T Method()
{
...
return Create();
}
}
class MyClass1 : MyClass<MyClass1>
{
protected override MyClass1 Create() => new MyClass1();
}
class MyClass2 : MyClass<MyClass2>
{
protected override MyClass2 Create() => new MyClass2();
}
它工作正常,但是合同看起来太奇怪了。当然,我可以提取类似IMyInterface
的东西,然后返回它而不是类。但是,我必须保留原始合同,因为它也包含特定的方法。
更新:因此,奇怪的是粗体-类 MyClass1 :MyClass << strong> MyClass1 >
答案 0 :(得分:4)
这是通常的所谓的自类型问题(您有Method()
应该返回与调用它的对象相同的类型)。您的解决方案3看起来很像F边界量化。但是,这是C#,而不是Java,因此我们可以使用扩展类做得更好。
通过添加绑定在MyClass
上的where T : MyClass
,可以确保仅在T
的子类上调用这些方法。
// Put all your shared methods in generic classes in here.
public static class MyMethods
{
public static T Method<T>(this T x) where T : MyClass
{
...
}
}
您的类变化不大,只是它们根本不需要提及Method
(或其他共享方法)。
public abstract class MyClass
{
...
}
public class MyClass1 : MyClass
{
...
}
public class MyClass2 : MyClass
{
...
}
答案 1 :(得分:3)
是的,只有一个创建方法看起来有点怪异。
因为您有两个类MyClass1和MyClass2,它们具有特定的不同方法,并且只有基本方法是常见的(您将它们放在基类中),所以我认为您可以使用Abstract工厂模式。
public class ClassFactory: IClassFactory
{
public MyClass Create()
{
if (some condition)
return new MyClass1;
return new MyClass2;
}
}
class MyClass
{
protected string CommonLogic()
{
//common logic
return string;
}
}
class MyClass1 : MyClass
{
public object SpecificMethod()
{
CommonLogic();
.....
}
}
class MyClass2 : MyClass
{
public object SpecificMethod2()
{
CommonLogic();
.....
}
}
在这种情况下,您将没有重复的代码,并且您将拥有某个类,该类将负责创建类并知道何时以及哪个类返回。 +您将在这里轻松使用IoC。
希望我的回答对您有所帮助。
答案 2 :(得分:0)
在一些罕见的情况下,可能需要自引用类型约束,但是我不相信这是其中之一。
似乎您要使用工厂(创建)模式,并使这些工厂返回不同的具体类型。但是同时,您说的是这些具体类型都有一些共同点,由基类指定。
常规方法是在接口(如您建议的IMyInterface)中定义通用功能,然后从Create方法返回该功能。这将捕获具体类的多态方面。然后的问题是如何捕获在具体类型中实现的其他方法。为此,只需定义其他接口即可捕获由多个以上具体类实现的各种功能集群。
在您完成此操作后,如果还剩下一点点和单调的功能,我想说,通过转换来处理它们是最简单的-那时,功能仅是其中之一具体课程。如果您想闭着眼睛飞行,可以使用“动态”类型而不是强制类型。
此外,通常在对象实例中未定义Create方法,换句话说,通常对象不是它们自己的工厂。通常,它们是静态的或在单独的工厂类中。在当前情况下,进行一些反思可以帮助您处理具有多个派生类型的事实。除了下面显示的内容外,还有多种方法可以做到这一点。
所以……也许是这样的:
public interface ICommonFunctionality
{
void SomethingThatEveryoneCanDo();
// ... other common functionality
}
public interface IAdditionalFunctionality1
{
void SomethingThatAFewCanDo();
// ... other special functionality
}
public interface IAdditionalFunctionality2
{
void SomethingThatOthersCanDo();
// ... other special functionality
}
public class MyClass : ICommonFunctionality
{
static public ICommonFunctionality Create(Type derivedType)
{
if (!typeof(ICommonFunctionality).IsAssignableFrom(derivedType)) { throw new ArgumentException(); }
return derivedType.CreateInstance() as ICommonFunctionality;
}
virtual public void SomethingThatEveryoneCanDo() { /* ... */ }
}
public class MyClass1 : MyClass, IAdditionalFunctionality1
{
public void SomethingThatAFewCanDo() { /* ... */ }
}
public class MyClass2 : MyClass, IAdditionalFunctionality1, IAdditionalFunctionality2
{
public void SomethingThatAFewCanDo() { /* ... */ }
public void SomethingThatOthersCanDo() { /* ... */ }
}
public class MyClass3 : MyClass, IAdditionalFunctionality2
{
public void SomethingThatOthersCanDo() { /* ... */ }
}
public static class TypeHelpers
{
public static object CreateInstance(this Type type, bool required = true)
{
System.Reflection.ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
if (required && ctor == null) { throw new InvalidOperationException("Missing required constructor."); }
return ctor?.Invoke(null);
}
}
P.S。我已经将基类方法设为虚拟,这取决于您的情况是可选的。