Перейти к содержимому

Фотография

Интересный примерИнкапсуляция и наследование в C#


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 21

#1
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений
Рассмотрим следующий пример на C#:
using System;

namespace ConsoleApplication1
{
	class Base
	{
		private int i = 5;
		private void Foo()
		{
			Console.WriteLine("Hello from private Foo()");
		}
		public static void Main()
		{
			Derived d = new Derived();
			d.i += 8;
			d.Foo();
			Console.WriteLine("d.i = {0}", d.i);
			Console.ReadLine();
		}	
	}

	class Derived : Base
	{   
	}

}
По правилам, прямой доступ к членам класса, объявленным с модификатором private, возможен только из этого же класса. Если необходим доступ к таким членам из производного класса, для этого имеется модификатор protected. Но пример компилируется и работает без единой ошибки! Я этого не могу объяснить. А вы?
  • 0

#2
at_developer

at_developer

    Читатель

  • Гость
  • 8 сообщений
Интересно
  • 0

#3
yedyge

yedyge
  • Свой человек
  • 879 сообщений
я, конечно, c# не знаю, но не находится ли вызов private void Foo() всё таки внутри класса Base, так же как и public static void Main()?
  • 0

#4
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений
Кстати, если Main() сделать тоже private, программа все равно компилируется и работает без ошибок!

Непонятно, зачем во всех книгах Main() всегда явно объявляют public... :dandy:
  • 0

#5
yedyge

yedyge
  • Свой человек
  • 879 сообщений
"private private видит издалека"
мэйн и фу члены одного класса басе, который скрывает фу от внешнего мира и публикует мэйн.
член члена внутре должен хорошо видеть, вроде.

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

#6
Havoc

Havoc
  • Завсегдатай
  • 296 сообщений
/**/

Сообщение отредактировал Havoc: 14.05.2007, 17:23:08

  • 0

#7
Коляныч

Коляныч
  • В доску свой
  • 2 773 сообщений

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

Но ведь так и происходит... Вот если вынести Main в другой класс, хотя бы в Derived, то должна быть ошибка.
  • 0

#8
T. Anre

T. Anre

    Data Miner

  • В доску свой
  • 2 327 сообщений

Кстати, если Main() сделать тоже private, программа все равно компилируется и работает без ошибок!

Непонятно, зачем во всех книгах Main() всегда явно объявляют public... :laugh:

Объявление main-функции - дело музыканта на СиДиезе, т.к. точных требований к определению в документации нет.
  • 0

#9
T. Anre

T. Anre

    Data Miner

  • В доску свой
  • 2 327 сообщений

я, конечно, c# не знаю, но не находится ли вызов private void Foo() всё таки внутри класса Base, так же как и public static void Main()?

Примерно, так и есть :laugh:
  • 0

#10
prodovets

prodovets

    Читатель

  • Гость
  • 8 сообщений
Console.WriteLine("");

Console.WriteLine("");
  • 0

#11
Sham

Sham
  • Гость
  • 7 сообщений
Пример компилируется, так как в классе Derived нет обращения к приватным полям и методам предка.
Попробуй в Derived класс добавить к метод, в котором будешь вызывать приватный метод предка или обращаться к приватному полю, тогда должно ругнуться.

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


Сообщение отредактировал Sham: 17.05.2007, 23:36:20

  • 0

#12
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

Пример компилируется, так как в классе Derived нет обращения к приватным полям и методам предка.

В данном примере есть обращение из переменной производного класса к приватным полям и методам класса-предка. Его трудно не заметить - см. код примера.

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

#13
Sham

Sham
  • Гость
  • 7 сообщений
Я имел ввиду что нет явного обращения и в данном примере срабатывает наследование, т.е. что может предок, то может и его потомок.
См.

Попробуй в Derived класс добавить к метод, в котором будешь вызывать приватный метод предка или обращаться к приватному полю, тогда должно ругнуться.


  • 0

#14
Sham

Sham
  • Гость
  • 7 сообщений
Да и еще, если в в Derived классе будет обращение к приватным полям или методам предка, то сработает механизм инкапсуляции(скрытие реализации) и выдаст ошибку.
  • 0

#15
Коляныч

Коляныч
  • В доску свой
  • 2 773 сообщений

В данном примере есть обращение из переменной производного класса к ...

Такого понятия даже нету - обращение может быть из метода, а не из переменной. Происходит обращение из метода Base.Main к приватной переменной Base.i, поэтому никак не возьму в толк где ты углядел криминал.
  • 0

#16
Sham

Sham
  • Гость
  • 7 сообщений


В данном примере есть обращение из переменной производного класса к ...

Такого понятия даже нету - обращение может быть из метода, а не из переменной.

Верно подмеченно, а я это пропустил :D
Кажется тема превращается во флейм.
  • 0

#17
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

Такого понятия даже нету - обращение может быть из метода, а не из переменной.

Расскажи, что курил перед тем, как заявить такое?

Происходит обращение из метода Base.Main к приватной переменной Base.i,

Не из метода Base.Main, а из объектной переменной, имя которой должно быть обязательно указано перед именем вызываемого метода или именем поля, к которому происходит обращение (поскольку они не объявлены как static). В данном примере эта объектная переменная имеет тип класса-наследника.

поэтому никак не возьму в толк где ты углядел криминал.

Нет никакого криминала, все законно. Я просто привел интересный (на мой взгляд) пример. Он интересен тем, что атрибут private как у метода, так и у поля в базовом классе в данном случае не влияет на их доступность из переменной производного класса.
  • 0

#18
Коляныч

Коляныч
  • В доску свой
  • 2 773 сообщений


Такого понятия даже нету - обращение может быть из метода, а не из переменной.

Расскажи, что курил перед тем, как заявить такое?

Вижуал, по-моему всё написано куда уж более ясно и точно. Если у тебя некое своеобразное представление о разграничениях доступа, то это имхо твои личные проблемы и к ООП языкам они отношения не имеют.



Происходит обращение из метода Base.Main к приватной переменной Base.i,

Не из метода Base.Main, а из объектной переменной, имя которой должно быть обязательно указано перед именем вызываемого метода или именем поля, к которому происходит обращение

Либо ты всё шиворот на выворот перепутал, либо читай выше.



поэтому никак не возьму в толк где ты углядел криминал.

Нет никакого криминала, все законно. Я просто привел интересный (на мой взгляд) пример. Он интересен тем, что атрибут private как у метода, так и у поля в базовом классе в данном случае не влияет на их доступность из переменной производного класса.

Имхо тебя смутил всего лишь тот факт, что в шарпе апкаст Derivet->Base происходит неявно, без необходимости писать static_cast<Base>(d). Других сложностей для понимания в упор не вижу.
  • 0

#19
Visual1

Visual1
  • В доску свой
  • 1 198 сообщений

Вижуал, по-моему всё написано куда уж более ясно и точно. Если у тебя некое своеобразное представление о разграничениях доступа, то это имхо твои личные проблемы и к ООП языкам они отношения не имеют.

У меня "своеобразное представление" и "личные проблемы"? Хм, вроде бы раньше не было такого в твоей манере - переходить на личности. По теме: состояние класса должно быть надежно защищено - надеюсь, не станешь с этим спорить? А как это обеспечить? Сделать класс изолированным (sealed)? Это работает, но изолированные классы не всегда удобны в использовании (производные типы нужны довольно часто, да и что это за ООП без наследования). Изолированным класс следует делать только если заранее известно, что он не предназначен для наследования. Это трудно предсказать - и поэтому не зря компилятор C# делает любой класс по умолчанию неизолированным.

Поля данных класса всегда следует объявлять private - элементарное правило, думаю, никто не станет с этим спорить. Но, как видно из приведенного примера, это тоже не всегда помогает. Я показал одну из таких скрытых опасностей - дальше можете поступать по своему усмотрению:
а) пользоваться этим в своей практической работе (рекомендую);
б) говорить про меня все, что угодно (что у меня "личные проблемы с пониманием языков ООП" и т.д.).
  • 0

#20
yedyge

yedyge
  • Свой человек
  • 879 сообщений
поясните криминал на пальцах, пожалуйста.
в каком операторе по вашему пониманию он сокрыт, вплоть до идентификаторов.
  • 0


Количество пользователей, читающих эту тему: 1

пользователей: 0, неизвестных прохожих: 1, скрытых пользователей: 0

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.