Объявление свойства в интерфейсе с установщиком, доступным для наследников, но не для экземпляров - PullRequest
0 голосов
/ 31 марта 2019

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

public interface Enforcer
{
  string Propy { get; set; }
}

Между интерфейсом и реальными классами мне нужно использовать абстрактную базукласс для принудительного применения подписи конструктора.Затем класс реализатора и класс-наследник выглядят так:

public class Implementer : Enforcer
{
  public string Propy { get; set; }

  public Implementer(string propy) { Propy = propy; }
}

Теперь, если я создаю экземпляр этого класса, у меня есть произвольный доступ к свойству, которое я хочу ограничить.Я не могу объявить сеттер как частный или защищенный, потому что модификаторы доступности не могут использоваться на методах доступа в интерфейсе.Я не могу сделать свойство полностью приватным, потому что мне нужно получить к нему доступ (конечно, только для чтения) в классе бегуна.

public class Inheritor : Implementer
{
  public Inheritor(string propy) : base(propy) { }
}

public class Instantiator
{
  public void Main()
  {
    Inheritor thing = new Inheritor("blopp");
    string propy = thing.Propy;
    thing.Propy = "bzz";
  }
}

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

Ответы [ 3 ]

1 голос
/ 31 марта 2019

В интерфейсе вы не можете ограничить доступ к свойствам, поэтому я не думаю, что вы можете заставить классы, которые реализуют этот интерфейс, ограничивать этот доступ.

В качестве альтернативы вы можете использовать абстрактный класс, в котором вы можете ограничить доступ, но не очень доброжелательный исполнитель может все же легко переопределить свойство ограниченного доступа абстрактного класса.

interface IMyClass
{
    string MyProperty { get; } // this does nothing against implementing a setter!
}

abstract class MyAbstracClass : IMyClass
{
    string MyProperty { get; protected set; } // otherwise we cannot set it from inheritors
}

class MyClass : MyAbstractClass
{
    public new string MyProperty { get; set; } // nothing stops this!
    public MyClass (string prop) => MyProperty = prop;
}

Параметр абстрактного класса означает , что означает, что разработчик не может "случайно" раскрыть свойство. Даже если вам do удастся скрыть это, любой разработчик, который действительно, действительно хочет получить доступ к частной собственности, может в любом случае просто использовать отражение. Это также не происходит случайно, и всегда должно поднимать красные флажки при проверке кода!

0 голосов
/ 31 марта 2019
public class Implementer : Enforcer
{
    private readonly string _propy;

    public string Propy
    {
        get => _propy;
        set => throw new InvalidOperationException();
    }

    public Implementer(string propy) { _propy = propy; }
}

выдает исключение, когда оно установлено, или вы можете просто изменить свой интерфейс, чтобы получать и использовать только закрытый набор в вашей реализации

0 голосов
/ 31 марта 2019
public class Implementer : Enforcer
{
    private string _propy;
    public string Propy
    { 
        get
        {
            return _propy;
        }
        set
        {
            // do nothing. so readonly.
        }
    }
    public Implementer(string propy) { _propy = propy; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...