Почему я не могу получить доступ к защищенным членам C #, кроме как так?

В prepareForSegue вы не можете получить доступ к @IBOutlet s контроллера точки назначения, потому что они еще не настроены. Вы должны назначить изображение свойству контроллера представления назначения, а затем переместить его на место в viewDidLoad:

В контроллере представления источника:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "toBrowsePage" {
        let dvc = segue.destinationViewController as! ListPage
        dvc.newImage = postingImage.image
    }
}

В режиме назначения контроллер:

class ListPage: UIViewController {
    @IBOutlet weak var browsingImage: UIImageView!
    var newImage: UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        browsingImage.image = newImage
    }
}
37
задан Community 23 May 2017 в 12:17
поделиться

4 ответа

"Защищенное" ключевое слово означает, что только тип и типы, которые происходят из того типа, могут получить доступ к участнику. D не имеет никаких отношений к C, поэтому не может получить доступ к участнику.

у Вас есть несколько опций, если Вы хотите смочь получить доступ к тому участнику

  • , Делают это, общественность
  • Делает это внутренним. Это позволит любым типам получать доступ к участнику в рамках того же блока (или другие блоки должны Вы добавлять, друг)
  • Получают D из РЕДАКТИРОВАНИЯ C

, Этот сценарий вызывается в разделе 3.5.3 из спецификации C#.

причина, которую это не позволяется, состоит в том, потому что она допускала бы перекрестные вызовы иерархии. Предположите, что в дополнение к D, был другой базовый класс C по имени E. Если бы Ваш код мог бы скомпилировать его, позволил бы D получать доступ к участнику E.F. Этот тип сценария не позволяется в C# (и я верю CLR, но я не делаю 100% знают).

EDIT2, Почему это плохо

Протест, это - мое мнение

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

sealed class MyClass : C {
  override F(D d) { ... } 
}

Рассматривает то, что происходит, если F является несколько строго ограниченной во времени функцией. С текущим поведением я могу рассуждать о правильности моего класса. В конце концов, существует только два случая где MyClass. F назовут.

  1. , Где это вызывается в C
  2. , Где я явно вызываю его в MyClass

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

Теперь, если C# действительно позволяет перекрестный защищенный доступ иерархии, я не могу сделать такую гарантию. Любой в совершенно другом блоке может приехать и произойти из C. Затем они могут назвать MyClass. F по желанию. Это делает абсолютно невозможным рассуждать о правильности моего класса.

17
ответ дан JaredPar 23 May 2017 в 22:17
поделиться

Причина это не работает, состоит в том, потому что C# не позволяет перекрестную иерархию, звонящую защищенных методов. Скажите, что было класс E, который также произошел от C:

  C
 / \
D   E

Затем ссылка Вы пытаетесь обратиться к методу, мог на самом деле быть экземпляр типа E, и таким образом метод мог решить во времени выполнения к E.F. Это не разрешено в C#, поскольку D не может звонить E защищенные методы, потому что E находится в другом ответвлении иерархии, т.е.

var d = new D();
var e = new E();
d.G(e); // oops, now this will call E.F which isn't allowed from D

Это имеет смысл, потому что ключевое слово protected означает, что участник" доступен в его классе и экземплярами производного класса ", и E.F не является членом D.

38
ответ дан Greg Beech 23 May 2017 в 22:17
поделиться

Даже при том, что D, наследовался C, D не может получить доступ к защищенным участникам C. D может получить доступ к защищенному D (и частный!) участники, поэтому при помещении другого экземпляра D там вместо C, все работало бы. Но поскольку Greg заявил, C мог действительно быть чем-то совершенно другим, и потому что компилятор не знает, каков C действительно, это должно препятствовать тому, чтобы D получил доступ к чему-то, к чему D не может на самом деле смочь получить доступ.

ряд А сообщений, объясняющих это с точки зрения компилятора C#:

11
ответ дан BCS 23 May 2017 в 22:17
поделиться

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

Подводя итог:

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

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

PS. Такое же поведение реализовано в Java.

1
ответ дан 27 November 2019 в 03:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: