2010-08-26 4 views
0

у меня есть вопрос по поводу следующего кода:с использованием статического свойства абстрактного класса внутри общего класса, который работает на подклассы абстрактного класса

abstract class a 
{ 
    public static string x; 
} 



class b<c> where c : a 
{ 
    public void f() 
    { 
     c.x=10; 
    } 
} 

Этот код не компилируется. Я получаю сообщение об ошибке c.x = 10; , Проблема в том, что он выглядит так, как будто условие where c:a не имеет никакого эффекта. Может кто-нибудь объяснить, почему это ошибка? Не правда ли, что x делится как статический член всеми дочерними элементами? И есть ли способ обойти эту проблему?

То, что я пытаюсь достичь, заключается в следующем: у меня есть подкласс a, все объекты которого имеют общее свойство, и это свойство должно быть установлено через f() в родовом классе b. Это нормально, если я заменю рассматриваемое заявление на a.x = 10? Если нет, то каким образом a.x отличается от c.x (или h.x, где h является подклассом a)?

+0

Я не совсем уверен, чего вы пытаетесь достичь. Можете ли вы расширить? – dtb

+0

Позвольте мне добавить немного более подробную информацию, чтобы помочь лучше понять требование: «a» представляет собой абстракцию для работы; поля в задании будут использованы для запуска процесса. любой данный подкласс «a» представляет собой конкретный тип работы. пусть «k» - один из таких подклассов. все экземпляры «k» имеют один общий атрибут. это верно для всех видов работы. существует другой класс «b», который работает над любой работой (т. е. «b» работает с использованием любого подкласса «a»). Я пытаюсь установить общий атрибут для заданного типа задания через «b». Есть ли способ достичь этого? – Aadith

+0

Помимо всех комментариев о статичности, вы также пытаетесь присвоить 'int' (10) место хранения' string' (x). AFAIK, это тоже не полетит. –

ответ

8

Статические элементы не наследуются, хотя смутно можно получить доступ к статическому элементу через производный тип. Например, в следующем коде

class P 
{ 
    public static string X; 
} 

class Q : P { } 

class R : P { } 

вы можете получить доступ к P.X через P.X или Q.X или R.X, но это по-прежнему то же самое поле:

P.X = "Hello"; 
Q.X = "World"; 
Console.WriteLine(R.X); // prints "World" 

Как вы обнаружили, вы не можете сделать это с типичными параметрами типа. Но доступ к X, хотя параметр типа на самом деле не имеет большого смысла, потому что все, что вы меняете, - P.X, которое вы пишете напрямую без параметра типового типа.


Я не совсем уверен, чего вы пытаетесь достичь. Если у вас есть абстрактный класс A и хотите, чтобы все экземпляры типов, которые вытекают из A иметь определенное свойство, можно определить следующим образом:

abstract class A 
{ 
    public abstract string X 
    { 
     get; 
    } 
} 

class A1 : A 
{ 
    public override string X 
    { 
     get { return "A1"; } 
    } 
} 

class A2 : A 
{ 
    public override string X 
    { 
     get { return "A2"; } 
    } 
} 

Если вы хотите связать немного информации с типом (не экземпляр), вы можете определить статическое поле, которое параметрироваться с типом, используя общий класс:

class Info<T> 
{ 
    public static string X; 
} 

Info<A1>.X = "Hello"; 
Info<A2>.X = "World"; 

Console.WriteLine(Info<A1>.X); // prints "Hello" 
Console.WriteLine(Info<A2>.X); // prints "World" 

что об этом?

abstract class Job 
{ 
    public abstract string ExePath 
    { 
     get; 
    } 

    public void Execute(string[] args) 
    { 
     Console.WriteLine("Executing {0}", this.ExePath); 
    } 
} 

abstract class Job<T> where T : Job<T> 
{ 
    public override string ExePath 
    { 
     get { return JobInfo<T>.ExePath; } 
    } 
} 

class ConcreteJob1 : Job<ConcreteJob1> { } 

class ConcreteJob2 : Job<ConcreteJob1> { } 

static class JobInfo<T> where T : Job<T> 
{ 
    public static string ExePath; 
} 

static class JobInfoInitializer 
{ 
    public static void InitializeExePaths() 
    { 
     JobInfo<ConcreteJob1>.ExePath = "calc.exe"; 
     JobInfo<ConcreteJob2>.ExePath = "notepad.exe"; 
    } 
} 

Это точно соответствует процессу, который вы описываете в своем комментарии. Он должен работать, хотя я не планирую настраивать модель работы.

0

Если вы хотите другой статический магазин подкладочный для каждого подкласса, но хотят, чтобы иметь возможность доступа к нему из экземпляра, полиморфно, вы можете сделать что-то вроде этого:

abstract class A 
{ 
    public abstract string X { get; set; } 
} 

class D : A 
{ 
    private static string _x; 

    public override string X 
    { 
     get { return _x; } 
     set { _x = value; } 
    } 
} 

Различные подклассы А может обеспечить их собственную реализацию X, включая использование статического хранилища резервных копий, если это желательно. Обратите внимание, что это не обязательно хорошая идея, так как это сложное глобальное состояние (претендующее на свойство экземпляра) может затруднить понимание и поддержку вашего кода.

0

Это ошибка, так как c является generic type parameter, не тип. Статические элементы доступны только через типы.

Все в порядке, если я заменю заявление с a.x = 10? Если нет, то каким образом a.x отличается от c.x (или h.x где h является подклассом a)?

Вы действительно можете заменить заявление на a.x=10;. Как вы заметили, это означает, что b.x, c.x и d.x все равно равны 10.

+0

За исключением того, что x является строкой не int, но это история различий –

Смежные вопросы