Метод с абстрактным классом в качестве параметра

У меня есть абстрактный класс A, от которого я получил классы B и C. Класс A предоставляет абстрактный метод DoJOB(), который реализуется обоими производными классами.

Есть класс X, внутри которого есть методы, которым нужно вызывать DoJOB(). Класс X не может содержать код, подобный B.DoJOB() или C.DoJOB().

Пример:

public class X
{
private A foo;

public X(A concrete)
{
foo = concrete;
}

public FunnyMethod()
{
foo.DoJOB();
}

}

При создании экземпляра класса X я хочу решить, какой производный класс (B или C) должен использоваться. Я думал о передаче экземпляра B или C с помощью конструктора X.

X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()

kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()

Мой тест показал, что объявление метода с параметром A не работает. Я что-то упускаю? Как я могу реализовать это правильно?

(A является абстрактным, его нельзя создать)

EDIT: Извините, я что-то забыл.

класс A является общим абстрактным синглтоном:

abstract public class A<T> where T : A<T>
{
    ....
}

public sealed class B : A<B>
{
    .....
}

public sealed class C : A<C>
{
    .....
}

См. пример: http://www.c-sharpcorner.com/UploadFile/snorrebaard/GenericSingleton11172008110419AM/GenericSingleton.aspx

Под заголовком «Решение с универсальным синглтоном в качестве абстрактного класса»


person Ferhat    schedule 06.01.2011    source источник
comment
Какую ошибку вы получаете из этого? Ошибка компиляции? Мне кажется нормально...   -  person Marnix    schedule 07.01.2011
comment
Вам нужно будет более конкретно указать, что вы подразумеваете под неработающим.   -  person Anon.    schedule 07.01.2011


Ответы (4)


Для вашего редактирования:

void Main()
{
var kewl = new X<C>(new C());
kewl.FunnyMethod(); //calls C.DoJOB()

var kewl2 = new X<B>(new B());
kewl2.FunnyMethod(); // calls B.DoJOB()

}

public class X <T> where T : A<T>
{
    private A<T> foo;

    public X(A<T> concrete)
    {
        foo = concrete;
    }

    public void FunnyMethod()
    {
        foo.DoJOB();
    }
}

public abstract class A<T> where T : A<T>
{
    public abstract void DoJOB();
}

public class B : A<B>
{
    public override void DoJOB()
    {
        Console.WriteLine("B");
    }
}

public class C : A<C>
{
    public override void DoJOB()
    {
        Console.WriteLine("C");
    }
}
person Rob    schedule 06.01.2011
comment
Спасибо за ответ. Мне очень помог. - person Ferhat; 08.01.2011

Вы, должно быть, ошиблись в тесте, код работает нормально:

void Main()
{
X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()

kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()

}

public class X
{
    private A foo;

    public X(A concrete)
    {
        foo = concrete;
    }

    public void FunnyMethod()
    {
        foo.DoJOB();
    }
}

public abstract class A
{
    public abstract void DoJOB();
}

public class B : A
{
    public override void DoJOB()
    {
        Console.WriteLine("B");
    }
}

public class C : A
{
    public override void DoJOB()
    {
        Console.WriteLine("C");
    }
}

Выходы:
C
B

person Rob    schedule 06.01.2011
comment
Отредактировал мой вопрос. Забыл сказать, что A — это общий абстрактный одноэлементный класс. Смотрите пример по ссылке. - person Ferhat; 07.01.2011

Работает на меня. я получаю ожидаемое

I did something interesting!
So Did I!

когда я запускаю его.

Вставьте это в свою Visual Studio и курите.

using System;

namespace TestDrive
{
    class Program
    {
        static void Main( string[] args )
        {
            ServiceConsumer x = new ServiceConsumer( new ConcreteService2() ) ;

            x.FunnyMethod() ;

            return ;
        }

    }

    abstract class AbstractService
    {
        public abstract void DoSomethingInteresting() ;
    }

    class ConcreteService1 : AbstractService
    {
        public override void DoSomethingInteresting()
        {
            Console.WriteLine("I did something interesting!");
            return ;
        }
    }

    class ConcreteService2 : ConcreteService1
    {
        public override void DoSomethingInteresting()
        {
            base.DoSomethingInteresting() ;
            Console.WriteLine("So Did I!");
            return ;
        }
    }

    class ConcreteService : AbstractService
    {
        public override void DoSomethingInteresting()
        {
            Console.WriteLine("Not It's my turn to do something interesting!") ;
            return ;
        }
    }

    class ServiceConsumer
    {
        private AbstractService Service ;
        public ServiceConsumer( AbstractService serviceInstance )
        {
            this.Service = serviceInstance ;
            return ;
        }
        public void FunnyMethod()
        {
            Service.DoSomethingInteresting() ;
            return ;
        }
    }
}

Ваше здоровье!

person Nicholas Carey    schedule 06.01.2011

Я не уверен, что понимаю вопрос, вот моя реализация, и она работает:

пространство имен CSharpConsole {

public abstract class A {
    public abstract void Test();
}
public class B : A {
    public override void Test() {
        System.Console.WriteLine("B:Test called!");
    }
}
public class C : A {
    public override void Test() {
        System.Console.WriteLine("C:Test called!");
    }
}    
class Program {
    private A _concrete;
    public Program(A concrete) {
        _concrete = concrete;
    }
    public void DoTest() {
        _concrete.Test();
    }
    static void Main(string[] args) {
        Program pb = new Program(new B());
        pb.DoTest();
        Program pc = new Program(new C());
        pc.DoTest();
    }
}

}

person codephene    schedule 06.01.2011