C# 将此消息传递给基本构造函数
我试图为我正在编写的程序实现良好的设计模式。我有一个这样的班级结构C# 将此消息传递给基本构造函数,c#,constructor,abstract-class,derived-class,base-class,C#,Constructor,Abstract Class,Derived Class,Base Class,我试图为我正在编写的程序实现良好的设计模式。我有一个这样的班级结构 abstract class SomeBase { public SomeObject obj { get; protected set; } protected SomeBase(SomeObject x) { obj = x; } //Other methods and fields... } public class SomeDerived :
abstract class SomeBase
{
public SomeObject obj { get; protected set; }
protected SomeBase(SomeObject x)
{
obj = x;
}
//Other methods and fields...
}
public class SomeDerived : SomeBase
{
public SomeDerived() : base(new SomeObject(this))
{
}
}
现在,我确信您知道,您不能在基本构造函数中传递它,因为此时对象尚未初始化。无论如何,我真的希望有一个解决办法。允许SomeDerived()
处理基类字段的设置对我来说不是最佳做法。我想向上传递这个新对象。1)构造函数的设计是错误的——它看起来像实例的方法,但实际上是半实例的半方法
2) “具有模式的良好设计程序”不会像我们在这里看到的那样在聚合中的类之间产生直接的循环依赖关系-这两个类在创建时必须相互了解并使用(!!!)谁知道SomeObject如何处理其构造函数中的“this”
所以在“模式”中有两个问题——类之间的高度依赖性和初始化逻辑的封装不可用。所以我们必须找到“模式”的方法来解决它。。。隐马尔可夫模型。。怎么办
在代码u中,我看到派生类只为属性obj提供了自己的逻辑
你可以将其重写为自动初始化属性
public abstract class MyClass{
private SomeObject _obj ;
public SomeObject Obj {get { return _obj ?? (_obj = InitializeObj() );}} //no setter needed
protected abstract SomeObject InitializeObj();
}
public class MyRealClass:MyClass {
protected override SomeObject InitializeObj(){
return new VerySpecialSomeObject(this, other, another, 1, 2 , false, option: new Options());
}
}
对于您的示例,此类解决方案提供了单个“模式”,可赢得“多态性”)并获得额外奖励(如果“Obj”无法使用,则永远无法创建))这是不可能的,请在构造函数之后使用Init方法:
abstract class SomeBase
{
private SomeObject _obj { get; set; }
public SomeObject obj
{
get
{ // check _obj is inited:
if (_obj == null) throw new <exception of your choice> ;
return _obj;
}
}
protected SomeBase()
{
obj = null;
}
protected void Init()
{
obj = x;
}
//Other methods and fields...
}
public class SomeDerived : SomeBase
{
public SomeDerived() : base()
{
Init(new SomeObject(this));
}
}
抽象类SomeBase
{
私有SomeObject _obj{get;set;}
公共对象对象
{
得到
{//check\u obj已初始化:
如果(_obj==null)抛出new;
返回对象;
}
}
受保护的SomeBase()
{
obj=null;
}
受保护的void Init()
{
obj=x;
}
//其他方法和字段。。。
}
公共类some派生:SomeBase
{
public SomeDerived():base()
{
Init(newsomeobject(this));
}
}
实际上,基本构造函数中有它,因此不需要传递它
using System;
abstract class SomeBase
{
public SomeObject obj { get; protected set; }
protected SomeBase()
{
// Will be executed as 1st step
Console.WriteLine(1);
// "this" here is SomeDerived object
obj = new SomeObject((SomeDerived)this);
// If you don`t like to depend upon SomeDerived type here,
// you can do the same using the following line:
//obj = (SomeObject)Activator.CreateInstance(typeof(SomeObject), this);
}
}
class SomeObject
{
public SomeObject(SomeDerived obj)
{
if (obj.obj == null)
{
// Will be executed as 2nd step
Console.WriteLine(2);
// You have the reference to SomeDerived here
// But its properties are not yet initialized
// (both SomeDerived and SomeBase constructors are in the progress)
// So you should not access these properties
// in the SomeObject class constructor,
// but you can do it in any method of SomeObject class
// (at the time the method will be called all constructors are finished).
}
}
}
class SomeDerived : SomeBase
{
public SomeDerived()
{
// Will be executed as 3rd step
Console.WriteLine(3);
if (this.obj != null)
{
// You have the reference to SomeObject here,
// which itself already got an access to SomeDerived reference
}
}
}
class MainClass
{
public static void Main (string[] args)
{
var instance = new SomeDerived();
Console.WriteLine (instance.obj); // Outputs SomeObject
}
}
另一个解决方案是使用lambda表达式,因此some派生类将完全控制对它的引用如何传递到SomeObject中
using System;
abstract class SomeBase
{
public SomeObject obj { get; protected set; }
protected SomeBase(Func<SomeBase, SomeObject> someObjectInitilizer)
{
// Will be executed as 1st step
Console.WriteLine(1);
// "this" here is SomeDerived object
obj = someObjectInitilizer(this);
}
}
class SomeObject
{
public SomeObject(SomeDerived obj)
{
if (obj.obj == null)
{
// Will be executed as 2nd step
Console.WriteLine(2);
// You have the reference to SomeDerived here
// But its properties are not yet initialized
// (both SomeDerived and SomeBase constructors are in the progress)
// So you should not access these properties
// in the SomeObject class constructor,
// but you can do it in any method of SomeObject class
// (at the time the method will be called all constructors are finished).
}
}
}
class SomeDerived : SomeBase
{
public SomeDerived() : base((@this) => new SomeObject((SomeDerived)@this))
{
// Will be executed as 3rd step
Console.WriteLine(3);
if (this.obj != null)
{
// You have the reference to SomeObject here,
// which itself already got an access to SomeDerived reference
}
}
}
class MainClass
{
public static void Main (string[] args)
{
var instance = new SomeDerived();
Console.WriteLine (instance.obj); // Outputs SomeObject
}
}
使用系统;
抽象类SomeBase
{
公共SomeObject对象{get;protected set;}
受保护的SomeBase(Func SomeObjectInitializer)
{
//将作为第一步执行
控制台写入线(1);
//“this”这里是一些派生对象
obj=某个对象初始化器(此);
}
}
类对象
{
公共SomeObject(Some派生对象)
{
如果(obj.obj==null)
{
//将作为第二步执行
控制台写入线(2);
//你在这里有对SomeDerived的引用
//但其属性尚未初始化
//(某些派生构造函数和某些基本构造函数都在进行中)
//因此,您不应该访问这些属性
//在SomeObject类构造函数中,
//但是,您可以在SomeObject类的任何方法中执行此操作
//(在调用该方法时,所有构造函数都已完成)。
}
}
}
类some派生:SomeBase
{
public SomeDerived():base((@this)=>new SomeObject((SomeDerived)@this))
{
//将作为第3步执行
控制台写入线(3);
如果(this.obj!=null)
{
//这里有对某个对象的引用,
//它本身已经获得了对某个派生引用的访问权
}
}
}
类主类
{
公共静态void Main(字符串[]args)
{
var instance=new SomeDerived();
Console.WriteLine(instance.obj);//输出SomeObject
}
}
其他子类是否希望创建一个不引用此
的SomeObject
实例?如果没有,只需将该逻辑放入SomeBase
构造函数体:obj=newsomeobject(this)代码>你为什么想要这个?我不认为有必要。嗯,我确实认为我所做的是有用的。所以,我有一个在游戏中工作的状态机。有一个StateManager类,它包含3种不同类型的状态(操作、大小、漏洞)。各州需要有能力更新其他州并取代自己(这是我的教授的要求)。。。各州需要一个对他们改变的游戏对象的引用。状态管理器也保存此引用,以便将其传递到它们初始化的适当状态。问题在于GameObject构造函数传递了一个“GameObject2D(…):base(new StackManager(this))”我有一个解决方法,但这并不理想,因为GameObject2D的每个派生类都需要初始化其StateManager。作为对你的回答,乔恩,只有有状态的东西才需要。大多数都是游戏对象,唯一的例外可能是游戏或菜单有状态逻辑(可能)。也许我误解了,但我认为这对我的问题没有帮助。如果你读了我原始帖子下面的评论,我会更详细地描述这个问题。抱歉,这只是我的困惑。不。我想你误解了你的问题。你试图使一些东西“模式化”,但不理解任何模式下的基本问题(对象之间的最小表面积、依赖性最小化、类的分解、模块化)。因此,你使你的代码没有用处,甚至对你自己也不舒服!构造器-是你的问题!!!您尝试用构造函数来表达不平凡的构造逻辑——这不是模式。如果你没有琐碎的构造,你就必须使用工厂族的模式,而不是用重写的构造函数进行脑力崩溃谢谢。基本上我就是这么做的。我想我希望能有点魔力。哈哈,谢谢你简洁的回答,或者你可以做一个抽象的属性。较小的代码。不确定