0

次の非常に基本的な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;
        }
    }
}

コンストラクターが 2 つの内部変数の設定を処理するため、抽象クラス ( abstract public void?) が必要とし、呼び出す必要がない方法でコンストラクターを設定するにはどうすればよいでしょうか。technician.setup();クラス関数をクラス自体と同じ名前で呼び出すと、次のエラーが発生します。

エラー 1 'Whisperity': メンバー名はそれらを囲んでいるものと同じにすることはできません

また、私の他の質問は最適化についてです。次のようなものを実行できるように、コンストラクトtechnicianの外側で定義する方法はありますか?ifclassType technician = new classType();

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 + "...");
4

3 に答える 3

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();
于 2012-08-10T21:25:13.123 に答える
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値を自動的に取得します。

エリックJのクラスデザインのヒントも+1。階層の設計を使用して、変化するものをカプセル化する必要があります。これにより、呼び出し元のコードがはるかに透過的になり、コードベースを将来拡張しやすくなります。

于 2012-08-10T22:29:28.217 に答える
0

抽象クラスがコンストラクターを必要とし、technical.setup() を呼び出す必要がない方法でコンストラクターをセットアップするにはどうすればよいでしょうか。

クラスの動作を強制するためにロジックを構築する必要はありませんがabstract、その逆も同様です。Abstractclass は、子が従わなければならない stuf を定義します。

必要な変数を初期化する単純なパラメーターのない ctorをクラスで作成すると、オブジェクトが構築されるたびに、のデフォルトのctor が前に呼び出されるため、初期化が実行されます。abstractchildabstract

より明確にするために:

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"

これがあなたが求めているものでない場合は、明確にしてください。

于 2012-08-10T21:29:47.103 に答える