【问题标题】:Static member accessability through generic inheritance通过遗传继承的静态成员可访问性
【发布时间】:2018-08-25 22:54:42
【问题描述】:

我最近提出了一些相当时髦的单例工作,并发现我可以使用使用泛型的相同继承基础从任何唯一继承类型访问受保护的静态成员。我所说的一个例子如下:

public abstract class Class<T>
{
    protected static int number = 5;

    public void Print()
    {
        Console.WriteLine(number);
    }
}

public class ClassA : Class<ClassA>
{
}

public class ClassB : Class<ClassB>
{
    public ClassB()
    {
        number = 1;
    }
}

public class ClassC : Class<ClassC>
{
    public ClassC()
    {
        number = ClassA.number;//I don't want to be able to see "number"
    }
}

由于这里使用了泛型,每个唯一的继承类型都有自己的“编号”(这是我想要的)。但是我不喜欢在使用泛型时我可以从继承相同基类型的其他类型访问“数字”。有没有办法来解决这个问题?还有为什么会发生这种情况(我理解为什么没有泛型的继承会发生这种情况,但泛型会发生这种情况似乎不对)?

【问题讨论】:

  • 通常使用静态受保护变量是不好的做法。静态方法/变量的通常用例是无需实例化对象即可访问变量/方法。在这种情况下,将某些东西设为受保护或私有似乎很奇怪。如果您不介意我的询问,您的用例是什么?
  • 您可以将静态字段设为私有,然后在抽象类中实现受保护的实例方法来获取/设置此静态字段的值(或使用等效的受保护属性)。这样,ClassB 的实例就无法访问 ClassA 的静态字段...
  • @CamiloTerevinto 不,这是相关的,因为泛型类中的 static 变量仅对于给定的一组泛型类型是唯一的。也就是说,您可以更改Class&lt;ClassA&gt;.number 的值,但这不会更改Class&lt;ClassB&gt;.number 的值,因为Class&lt;ClassA&gt;Class&lt;ClassB&gt; 被视为两种独特的类型。
  • @juharr 呵呵,我们每天都在学习新东西。谢谢

标签: c# generics inheritance static protected


【解决方案1】:

我不喜欢在使用泛型时我可以从其他继承相同基类的类中访问“数字”。有没有办法解决这个问题?

唯一真正的解决方法是为每个类声明单独的private static 变量。这将使您无法从任何其他类类型中看到一个类类型中的数字变量。

public abstract class Class<T>
{
    private static int number = 5;

    public void Print()
    {
        Console.WriteLine(number);
    }
}

public class ClassA : Class<ClassA>
{
}

public class ClassB : Class<ClassB>
{
    private static int number;

    public ClassB()
    {
        number = 1;
    }
}

public class ClassC : Class<ClassC>
{
    private static int number;

    public ClassC()
    {
        number = 123; // Cannot see ClassA.number because it is private to `Class<T>`
    }
}

声明变量protected static 并将其与继承一起使用会导致副作用。当您所追求的行为是 private static 字段的行为时,尚不清楚为什么您会尝试这样做。

【讨论】:

  • “如果那是你想要的,你没有实现它。”? number = ClassA.number; ClassC的编号和ClassA的编号是两个不同的变量……它们都有自己的“编号”。也许我可以澄清一下,每个唯一的继承类型都有自己的“数字”变量。
  • 啊,好吧,我进行了测试,你是对的——你有不同的类类型,所以每个类都有不同的变量。对于所有实例,它仍然是同一个变量。
【解决方案2】:

您可以使用private 修饰符使静态成员对后代不可见。仅当您希望后代能够访问它时才使用受保护的。通用与非通用没有区别。

public abstract class Class<T>
{
    private static int number = 5;  //Private now

    public void Print()
    {
        Console.WriteLine(number);  //Works
    }
}

public class ClassA : Class<ClassA>
{
    //No number
}

public class ClassB : Class<ClassB>
{
    public ClassB()
    {
        number = 1;  //Will not compile
    }
}

public class ClassC : Class<ClassC>
{
    public ClassC()
    {
        number = ClassA.number;//Will not compile
    }
}

如果您希望静态变量只能被某些后代访问,而不能被其他后代访问,请在需要访问的继承链中的第一个类中定义该变量:

public abstract class Class<T>
{
}

public class ClassA : Class<ClassA>
{
    static private int number = 7;
}

public class ClassB : Class<ClassB>
{
    static private int number = 7;

    public ClassB()
    {
        ClassA.number = 5;  //Does not compile
        ClassB.number = 6;
    }
}

public class ClassC : Class<ClassC>
{
    static private int number = 7;

    public ClassC()
    {
        Console.WriteLine(ClassA.number);  //Does not compile
        Console.WriteLine(ClassB.number);  //Does not compile
        Console.WriteLine(ClassC.number);  //Compiles
    }
}

您不能在祖先类中定义某些内容并将其从后代中删除。

【讨论】:

  • 它不能是私有的,因为 ClassB 仍然需要访问它。例如只有直接继承者才能访问该变量。
  • 我猜它不适合。看起来他希望能够访问ClassCnumber 而不能访问ClassAnumber(我反对)
  • 我明白了。我已经修改了我的答案以适应。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
相关资源
最近更新 更多