请考虑以下非常基本的 C#代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Random random = new Random();
for (int i = 1; i <= 100; i++)
{
int num = random.Next(1000);
string it_type;
if (num == 666)
{
System.Console.Write("Antichrist/satanistic trips get. Enjoy! ");
JonSkeet technician = new JonSkeet(); // Needs more Super::$tatic
technician.setup();
it_type = technician.getITType();
}
else
{
Whisperity technician = new Whisperity();
technician.setup();
it_type = technician.getITType();
}
System.Console.WriteLine(it_type + "... Prepare for next iteration.");
}
System.Console.ReadLine();
}
}
abstract public class ITTechnician
{
protected string itt_type = "Noname person.";
protected bool isJonSkeet = false;
public string getITType()
{
return this.itt_type;
}
abstract public void setup();
}
public class JonSkeet : ITTechnician
{
public override void setup()
{
this.itt_type = "Jon Skeet";
this.isJonSkeet = true;
}
}
public class Whisperity : ITTechnician
{
public override void setup()
{
this.itt_type = "Whisperity";
this.isJonSkeet = false;
}
}
}
我如何能够以抽象类(abstract public void
?)需要它的方式设置构造函数,并且我不必调用technician.setup();
,因为构造函数需要注意设置两个内部变量。如果我调用类函数与类本身相同的名称,我会收到以下错误:
错误1'Whisperity':成员名称不能与其附件
相同
另外,我的另一个问题是优化问题。有没有办法在technician
构造之外定义if
,所以可以执行以下类似的操作:(这将省略classType technician = new classType();
行两次,或者它是否在C#中无法通过?)
string it_type;
// Register 'technician' as a variable here.
if (num = 666)
{
technician = new JonSkeet();
}
else
{
technician = new Whisperity();
}
it_type = technician.getITType();
System.Console.WriteLine(it_type + "...");
答案 0 :(得分:2)
回答您的问题
您可以在抽象类中提供带参数的构造函数。
abstract public class ITTechnician
{
public ITTechnician(string itt_type, bool isJonSkeet)
{
this.itt_type = itt_type;
this.isJonSkeet = isJonSkeet;
}
}
构建一个JonSkeet(如果它只是那么容易!)
JonSkeet jon = new JonSkeet("Jon Skeet", true);
有关课堂设计的建议
另一方面,我知道这是一个示例问题,但如果基类保存的信息可以区分继承它的类,那么您就不会很好地使用面向对象。
具体来说,这种设计会引导你做像
这样的事情ITTechnician itt = GetSomeInstance();
if (itt.IsJonSkeet)
{
BehaviorA();
else
{
BehaviorB();
}
做一些像
这样的事情要干得多abstract public class ITTechnician
{
public abstract void Behavior();
// ...
}
public class JonSkeet
{
public override Behavior()
{
// Do awesome things
}
}
允许将上述代码写为
ITTechnician itt = GetSomeInstance();
itt.Behavior();
答案 1 :(得分:0)
我如何能够以抽象的方式设置构造函数 上课需要它,我不需要打电话 technician.setup()
您不需要构造逻辑来强制abstract
类的行为,反之亦然。 Abstract
类定义了孩子必须遵循的stuf。
如果在abstract
类中创建一个简单的参数 ctor,它会初始化您需要的变量,每当构造child
对象时,abstract
的默认值为{{之前将调用1}},因此将执行初始化。
更清楚:
public class Child : Base
{
public Child(int x){
"Child".Dump();
}
}
public abstract class Base
{
public Base() {
//INIT VARIABLES HERE
"Base".Dump();
}
}
使用像
这样的结构 vaar ch = new Child();
生成结果
"Base"
"Child"
如果这不是您所要求的,请澄清。
答案 2 :(得分:0)
要在运行时发现类型,请使用GetType()
。无需创建自己的类型字符串字段。
除了类结构中的内在类型之外,唯一不同的是IsJonSkeet
。我们可以使用.NET属性来实现它,与使用Getter和Setter的传统私有/受保护字段相比,这是一种更现代和更具表现力的方式。
abstract public class ITTechnician
{
public bool IsJonSkeet { get; protected set; }
protected ITTechnician()
{
this.IsJonSkeet = false;
}
}
public class JonSkeet : ITTechnician
{
public JonSkeet()
{
this.IsJonSkeet = true;
}
}
public class Whisperity : ITTechnician
{
}
现在已经删除了你的itt_type字符串字段,Whisperity与基类相同,因此不需要构造函数进行任何初始化 - 它会自动获取其父级的IsJonSkeet值。
+1也是Eric J的课程设计技巧。您应该使用层次结构的设计来封装不同的内容,这使您的调用代码更加透明,并且代码库将来更容易扩展。