рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Объектно-ориентированное программирование как идеология программирования и как технология. Достоинства и недостатки

Объектно-ориентированное программирование как идеология программирования и как технология. Достоинства и недостатки - раздел Программирование, Объектно-Ориентированное Программ...

Объектно-ориентированное программирование как идеология программирования и как технология. Достоинства и недостатки.

В языке С# (созданном компанией Microsoft для поддержки среды .NET Framework) проверенные временем средства усовершенствованы с помощью самых… ООП — это целый набор концепций и идей, позволяющих осмыслить задачу, стоящую… В последнее время идея ООП, кардинально новая идеология написания программ, все более занимает умы программистов.…

Основные понятия объектно-ориентированного программирования — класс, объект, поле, метод, свойство.

Класс— это шаблон, который определяет форму объекта. Он задает как данные, так и код, который оперирует этими данными. Объекты — это экземпляры класса. Класс — это логическая абстракция. О ее реализации нет смысла говорить до тех пор, пока не создан объект класса, и в памяти не появилось физическое его представление. Данные содержатся в переменных экземпляров, а код — в методах. Класс определяет также ряд специальных членов данных и методов-членов, например статические переменные, константы, конструкторы, деструкторы, индексаторы, события, операторы и свойства.

Объявление объекта типа Building:

Building house = new Building();

Это объявление выполняет две функции. Во-первых, оно объявляет переменную с именем house классового типа Building. Но эта переменная не определяет объект, а может лишь ссылаться на него. Во-вторых, рассматриваемое объявление создает реальную физическую копию объекта и присваивает переменной house ссылку на этот объект. И все это — "дело рук" оператора new. Таким образом, после выполнения приведенной выше строки кода переменная house будет ссылаться на объект типа Building.

Оператор new динамически (т.е. во время выполнения программы) выделяет память для объекта и возвращает ссылку на него. Эта ссылка (сохраненная в конкретной переменной) служит адресом объекта в памяти, выделенной для него оператором new. Таким образом, в С# для всех объектов классов должна динамически выделяться память.

Есть и другие трактовки термина "класс", показывающие, в частности, чем класс отличается от объекта. Считайте, что класс — это просто новый тип данных (как char, int или long), с которым связаны некие методы. Объект же — это экземпляр типа, или класса. Определение класса как чертежа объекта. На базе класса — "чертежа" набора функциональных возможностей — можно создать объект, обладающий всеми возможностями этого класса.

Поле — член-переменная, содержащая некоторое значение и описанная внутри класса. В ООП поля иногда называют данными объекта. К полю можно применять несколько модификаторов в зависимости от того, как вы собираетесь это поле использовать. В число модификаторов входят static, readonly и const. Поля характеризуют свойства объектов класса. Когда создается новый объект класса, то этот объект представляет собой набор полей класса. Два объекта одного класса имеют один и тот же набор полей, но разнятся значениями, хранимыми в этих полях. Каждое поле имеет модификатор доступа, принимающий одно из четырех значений: public, private, protected, internal( Его назначение — заявить о том, что некоторый член известен во всех файлах, входящих в состав компоновочного, но неизвестен вне его. Проще говоря, член, отмеченный этим модификатором, известен только программе, но не где-то еще).

Метод — элемент класса, кот реализует вычисления или другие действия, выполняемые классом или экземпляром. Метод — это фрагмент кода, к кот можно обратиться по имени. Он описывается один раз, а вызываться может столько раз, сколько необходимо. У метода также есть спецификаторы доступа: public, private, protected, virtual, override, abstract.

Методы — это процедуры (подпрограммы), которые манипулируют данными, определенными в классе, и во многих случаях обеспечивают доступ к этим данным. Обычно различные части программы взаимодействуют с классом посредством его методов. Любой метод содержит одну или несколько инструкций. Каждый метод имеет имя, и именно это имя используется для его вызова. В общем случае методу можно присвоить любое имя. Имена методов сопровождаются парой круглых скобок. Например, если метод имеет имя getval, то в тексте будет написано getval (). Это помогает отличать имена переменных от имен методов.

Запись метода: доступ тип_возврата имя (список_параметров) {// тело метода}

Свойстваиногда называют "разумными" полями (smart fields), так как они на самом деле являются методами, которые клиенты класса воспринимают как поля. Они служат для организации доступа к полям класса. Свойство состоит из имени и пары аксессоров (get, set). Аксессоры используются для чтения содержимого переменной и записи в нее нового значения. Основное достоинство свойства состоит в том, что его имя можно использовать в выражениях и инструкциях присваивания подобно обычной переменной, хотя в действительности здесь будут автоматически вызываться get- и set-аксессоры.

[спецификатор] тип имя_свойства

{ get{return();}//получатель значения поля

set{}//установщик поля служит для его изменения

}

 

3. Класс. Синтаксис объявления класса. Ссылка на самого себя

Объектно-ориентированное программирование и проектирование построено на классах. Любую программную систему, выстроенную в объектном стиле, можно рассматривать как совокупность классов, возможно, объединенных в проекты, пространства имен, решения, как это делается при программировании в Visual Studio .Net. У класса две различные роли: модуля и типа данных. Класс - это модуль, архитектурная единица построения программной системы. Модульность построения - основное свойство программных систем. В ООП программная система, строящаяся по модульному принципу, состоит из классов, являющихся основным видом модуля.

Класс — это шаблон, который определяет форму объекта. Он задает как данные, так и код, который оперирует этими данными. Объекты — это экземпляры класса. Класс — это логическая абстракция. О ее реализации нет смысла говорить до тех пор, пока не создан объект класса, и в памяти не появилось физическое его представление. Данные содержатся в переменных экземпляров, а код — в методах. Класс определяет также ряд специальных членов данных и методов-членов, например: статические переменные, константы, конструкторы, деструкторы, индексаторы, события, операторы и свойства.

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

[атрибуты][модификаторы]class имя_класса [:список_родителей]

{// Объявление переменных экземпляров.

доступ тип переменная1; доступ тип переменнаяN;

доступ тип_возврата метод 1 (параметры) // Объявление методов

{ // тело метода}

доступ тип_возврата методN (параметры) {// тело метода}

Ссылка на самого себя

public Employee(string fullName, int empID) { this.fullName=fullName; //присвоение полю fullName значение параметра… this.empID=empID; }

Конструкторы и деструкторы. Функциональное назначение. Виды конструкторов.

Создание объектов происходит при объявлении сущности в момент ее инициализации. Пример создания объектов класса Person: Person pers1 = new Person(); Person pers2= new Person("Петрова");

Деструкторы класса

Средства языка С# позволяют определить метод, который должен вызываться непосредственно перед тем, как объект будет окончательно разрушен системой сбора мусора. Этот метод называется деструктором, и его можно использовать для обеспечения гарантии "чистоты" ликвидации объекта. Например, можно использовать деструктор для гарантированного закрытия файла, открытого некоторым объектом. Форма записи деструктора:

~имя_класса() {

// код деструктора

}

Таким образом, деструктор объявляется подобно конструктору за исключением того, что его имени предшествует символ "тильда" (~). (Подобно конструктору, деструктор не возвращает значения.) Чтобы добавить деструктор в класс, достаточно включить его как член. Он вызывается в момент, предшествующий процессу утилизации объекта. В теле деструктора указываются действия, которые, должны быть выполнены перед разрушением объекта.

Важно понимать, что деструктор вызывается только перед началом работы системы сбора мусора и не вызывается, например, когда объект выходит за пределы области видимости. Это означает, что нельзя точно знать, когда будет выполнен деструктор. Однако точно известно, что все деструкторы будут вызваны перед завершением программы. Применение деструкторов замедляет процесс сборки мусора.

 

Объекты и их жизненный цикл. Создание и уничтожение объектов.

Объекты — это экземпляры класса. Класс — это логическая абстракция. О ее реализации нет смысла говорить до тех пор, пока не создан объект класса, и… Рассмотрим создание объекта на примере класса Person. Person pers = new Person;

Инкапсуляция. Определение. Функциональное назначение. Реализация. Примеры применения

Инкапсуляция— это механизм программирования, который связывает код (действия) и данные, которыми он манипулирует, и при этом предохраняет их от вмешательства извне и неправильного использования. При связывании кода и данных создается объект. Другими словами, объект — это элемент, который поддерживает инкапсуляцию.

Код, данные или обе эти составляющие объекта могут быть закрытыми внутри него или открытыми. Закрытый код или закрытые данные известны лишь остальной части этого объекта и доступны только ей. Это означает, что к закрытому коду или данным не может получить доступ никакая другая часть программы, существующая вне этого объекта. Если код или данные являются открытыми, к ним (несмотря на то, что они определены внутри объекта) могут получить доступ другие части программы. Как правило, открытые части объекта используются для обеспечения управляемого интерфейса с закрытыми элементами. Основной единицей инкапсуляции в С# является класс. Класс определяет форму объекта. Он задает как данные, так и код, который будет оперировать этими данными.

В С# класс используется для создания объектов. Объекты — это экземпляры класса. Таким образом, класс — это по сути набор шаблонных элементов, которые показывают, как построить объект.

Код и данные, которые составляют класс, называются членами класса. Данные, определенные в классе, называются переменными экземпляра (instance variable), а код, который оперирует этими данными, — методами-членами (member method), или просто методами. "Метод" — это термин, применяемый в С# для обозначения подпрограммы.

Инкапсуляция, или утаивание информации, — это возможность скрыть внутреннее устройство объекта от его пользователей, предоставив через интерфейс доступ только к тем членам объекта, с которыми клиенту разрешается работать напрямую. Инкапсуляция подразумевает наличие границы между внешним интерфейсом класса (открытыми членами, видимыми пользователям класса) и деталями его внутренней реализации. Преимущество инкапсуляции для разработчика в том, что он может открыть те члены класса, которые будут оставаться статичными, или неизменяемыми, скрыв внутреннюю организацию класса, более динамичную и в большей степени подверженную изменениям. Как уже говорилось, в С# инкапсуляция достигается путем назначения каждому члену класса своего модификатора доступа — public, private или protected. Инкапсуляция позволяет изменить реализацию объекта без модификации основной части программы, если его интерфейс остался прежним. Простота модификации является важным критерием качества программы. Инкапсуляция позволяет использовать объект в другом окружении и быть уверенным в том, что он не испортит не принадлежащие ему области памяти, а также создавать библиотеки объектов для применения во многих программах.

Пример:

class EncapsulationExample

{

private double valueDouble;

private string valueString;

 

public double Value

{

get { return valueDouble; }

set

{

valueDouble = value;

valueString = value.ToString();

}

}

 

public string ValueString

{

get { return valueString; }

set

{

double tmp_value = Convert.ToDouble(value); //здесь может возникнуть исключение

valueDouble = tmp_value;

valueString = value;

}

}

}

 

Инкапсуляция. Свойства. Функциональное назначение. Реализация. Создание индексатора. Примеры применения.

Инкапсуляция — это механизм, объединяющий данные и обрабатывающий их код как единое целое. Инкапсуляцией называется включение различных мелких элементов в более крупный объект, в результате чего программист работает непосредственно с этим объектом. Это приводит к упрощению программы, поскольку из нее исключаются второстепенные детали. Инкапсуляцию можно сравнивать с работой автомобиля с точки зрения типичного водителя. Многие водители не разбираются в устройстве авто, но управляют им. Существует специальный интерфейс, который упрощает сложные операции работы двигателя, тормоза. Сказанное относится к инкапсуляции и ООП — многие подробности внутреннего устройства скрываются от пользователя, что позволяет ему сосредоточиться на решении конкретных задач. В ООП эта возможность обеспечивается классами, объектами и различными средствами выражения связей между ними.

В C# для инкапсуляции используются публичные свойства и методы объекта

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

спецификатор тип this [список_параметров]

{ get код_доступа

set код_доступа }

Список_параметров содержит одно или несколько описаний индексов, по которым выполняется доступ к элементу. Чаще всего используется один индекс целого типа. Код_доступа представляют собой блоки операторов, которые выполняются при получении (get) или установки (set) элемента массива. Пример:

const int Child_Max = 20; //максимальное число детей (константа)

Person[] children = new Person[Child_Max];

int count_children=0; //число детей

public Person this[int i] //индексатор с именем this

{

get {if (i>=0 && i< count_children)return(children[i]);

else return(children[0]);}

set

{

if (i==count_children && i< Child_Max)

{children[i] = value; count_children++;}

}

}

Имя у индексатора — this, в квадратных скобках в заголовке перечисляются индексы. В методах get и set, обеспечивающих доступ к массиву children, по которому ведется индексирование, анализируется корректность задания индекса. Закрытое поле count_children, хранящее текущее число детей, доступно только для чтения благодаря добавлению соответствующего метода-свойства. Запись в это поле происходит в методе set индексатора, когда к массиву children добавляется новый элемент.

Пример:

class EncapsulationExample

{

private double valueDouble;

private string valueString;

 

public double Value

{

get { return valueDouble; }

set

{

valueDouble = value;

valueString = value.ToString();

}

}

 

public string ValueString

{

get { return valueString; }

set

{

double tmp_value = Convert.ToDouble(value); //здесь может возникнуть исключение

valueDouble = tmp_value;

valueString = value;

}

}

}

Инкапсуляция. Скрытие членов класса. Функциональное назначение. Реализация. Примеры применения.

Управление доступом к членам класса достигается за счет использования четырех спецификаторов доступа: public, private, protected и internal. Модификатор protected применяется только при включении интерфейсов. Модификатор internal применяется в основном при использовании компоновочных файлов (assembly). Если некоторые методы класса A должны быть доступны для вызовов в методах класса B, являющегося потомком класса A, то такие методы следует снабдить атрибутом protected. Если некоторые методы должны быть доступны только для методов классов B1, B2 и так далее, дружественных по отношению к классу A, то такие методы следует снабдить атрибутом internal, а все дружественные классы B поместить в один проект. Назначение модификатора internal — заявить о том, что некоторый член известен во всех файлах, входящих в состав компоновочного, но неизвестен вне его. Проще говоря, член, отмеченный модификатором internal, известен только программе, но не где-то еще. Модификатор доступа internal чрезвычайно полезен при создании программных компонентов. Модификатор internal можно применить к классам и членам классов, а также к структурам и членам структур.

Спецификатор public разрешает доступ к соответствующему члену класса со стороны другого кода программы, включая методы, определенные внутри других классов. Спецификатор private разрешает доступ к соответствующему члену класса только для методов, определенных внутри того же класса. Таким образом, методы других классов не могут получить доступ к private-члену не их класса. Спецификатор доступа должен стоять первым в списке спецификаторов типа любого члена класса.

Общие принципы использования спецификаторов доступа public и private:

1. Члены, которые используются только внутри класса, следует определить как закрытые.

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

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

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

5. Методы, которые получают или устанавливают значения закрытых данных, должны быть открытыми.

6. Объявление переменных экземпляров открытыми допустимо, если нет причин делать их закрытыми.

Пример:

class EncapsulationExample

{

private double valueDouble;

private string valueString;

 

public double Value

{

get { return valueDouble; }

set

{

valueDouble = value;

valueString = value.ToString();

}

}

 

public string ValueString

{

get { return valueString; }

set

{

double tmp_value = Convert.ToDouble(value); //здесь может возникнуть исключение

valueDouble = tmp_value;

valueString = value;

}

}

}

 

Наследование. Функциональное назначение. Реализация. Примеры применения.

Насле́дование— механизм объектно-ориентированного программирования

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

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

Наследование (Генерализация) — объекты дочернего класса наследуют все свойства родительского класса.

Пример:

public class A { }

public interface I1 { }

public interface I2 { }

public class B : A, I1, I2 { }

Агрегация — объекты одного класса входят в объекты другого.

Пример:

class A

{

public class B : A { }

}

Наследование. Конструктор по умолчанию. Назначение.

позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются… Другими словами, класс-наследник реализует спецификацию уже существующего… При наследовании каждый класс должен позаботиться о создании собственных конструкторов. Он не может в этом вопросе…

Методы. Определение. Функциональное назначение. Способы реализации. Примеры применения.

Методы — это процедуры (подпрограммы), которые манипулируют данными, определенными в классе, и во многих случаях обеспечивают доступ к этим данным. Обычно различные части программы взаимодействуют с классом посредством его методов. Любой метод содержит одну или несколько инструкций. Каждый метод имеет имя, и именно это имя используется для его вызова. Запись метода:

доступ тип_возврата имя (список_параметров) {// тело метода }

public int Met() { return m; }//метод для получения значения m

Параметры исп для обмена инф с методом. Методы также имеют спецификаторы virtual, override, abstract…

Полиморфизм. Функциональное назначение. Способы реализации. Примеры применения.

 

Полиморфи́зм — возможность объектов с одинаковой спецификацией иметь различную реализацию.

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

Полиморфизм позволяет писать более абстрактные программы и повысить коэффициент повторного использования кода.

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

В основе полиморфизма, характерного для семейства классов, лежат три механизма:

• одностороннее присваивание объектов внутри семейства классов; сущность, базовым классом которой является класс предка, можно связать с объектом любого из потомков. Другими словами, для введенной нами последовательности объектов xk присваивание xi = xj допустимо для всех j >=i;

• переопределение потомком метода, наследованного от родителя. Благодаря переопределению, в семействе классов существует совокупность полиморфных методов с одним именем и сигнатурой;

• динамическое связывание, позволяющее в момент выполнения вызывать метод, который принадлежит целевому объекту.

Способы реализации: перегрузка методов и операций, виртуальные методы.

public class Worker : Man

{

//Виртуальный метод

public virtual void GiveMoney(int money)

{

Console.WriteLine("Получите "+money+" рублей");

}

}

 

public class Teacher : Worker

{

//Задаем необходимую функциональность

public override void GiveMoney(int money)

{

int bonus = 1000; //премиальные 1000 руб

money = money + bonus;

base.GiveMoney(money);

}

}

Вот простой пример, иллюстрирующий перегрузку методов:

public void ovlDemo() {}

// Перегружаем метод ovlDemo() для одного целочисленного параметра

public void ovlDemo(int a) { Console.WriteLine("Один параметр: " + a); }

Перегруз операций:

public class ComplexNumber

{

private int real;

private int imaginary;

 

public ComplexNumber() : this(0, 0) // constructor

{

}

 

public ComplexNumber(int r, int i) // constructor

{

real = r;

imaginary = i;

}

 

// Override ToString() to display a complex number in the traditional format:

public override string ToString()

{

return(System.String.Format("{0} + {1}i", real, imaginary));

}

 

// Overloading '+' operator:

public static ComplexNumber operator+(ComplexNumber a, ComplexNumber b)

{

return new ComplexNumber(a.real + b.real, a.imaginary + b.imaginary);

}

 

// Overloading '-' operator:

public static ComplexNumber operator-(ComplexNumber a, ComplexNumber b)

{

return new ComplexNumber(a.real - b.real, a.imaginary - b.imaginary);

}

}

 

Перегрузка методов. Функциональное назначение. Способ реализации. Примеры применения.

В С# два или больше методов внутри одного класса могут иметь одинаковое имя, но при условии, что их параметры будут различными. Такую ситуацию называют перегрузкой методов.

Перегрузка методов — один из способов реализации полиморфизма в С#. В общем случае для создания перегрузки некоторого метода достаточно объявить еще одну его версию. Об остальном позаботится компилятор. Но здесь необходимо отметить одно важное условие: все перегруженные методы должны иметь списки параметров, которые отличаются по типу и/или количеству. Методам для перегрузки недостаточно отличаться лишь типами возвращаемых значений.(Другими словами, тип возвращаемого значения не обеспечивает достаточную информацию для С#, чтобы можно решить, какой именно метод должен быть вызван). Конечно, перегруженные методы могут отличаться и типами возвращаемых значений. При вызове перегруженного метода выполняется та его версия, параметры которой совпадают (по типу и количеству) с заданными аргументами.

Вот простой пример, иллюстрирующий перегрузку методов:

public void ovlDemo() {}

// Перегружаем метод ovlDemo() для одного целочисленного параметра

public void ovlDemo(int a) { Console.WriteLine("Один параметр: " + a); }

Посредством перегрузки методов в С# поддерживается полиморфизм. В языке, который не поддерживает перегрузку методов, каждый метод должен иметь уникальное имя. Однако часто нужно реализовать один и тот же метод для различных типов данных. Возьмем, например, функцию, возвращающую абсолютное значение. В языках, которые не поддерживают перегрузку методов, обычно существует три или даже больше версий этой функции, причем их имена незначительно отличаются. Например, в языке С функция abs () возвращает абсолютное значение (модуль) целого числа, функция labs () возвращает модуль длинного целочисленного значения, а fabs () — модуль значения с плавающей точкой. Поскольку язык С не поддерживает перегрузку методов, каждая функция должна иметь собственное имя, несмотря на то, что все три функции выполняют по сути одно и то же действие. Это делает ситуацию сложнее, чем она есть на самом деле. Другими словами, при одних и тех же действиях программисту необходимо помнить имена всех трех (в данном случае) функций. Язык С# избавлен от ненужного "размножения" имен, поскольку все методы получения абсолютного значения могут использовать одно и то же имя. И в самом деле, библиотека стандартных классов С# включает метод получения абсолютного значения с именем Abs(). Этот метод перегружается С#-классом System.Math, что позволяет обрабатывать значения всех числовых типов, используя одно имя метода. Определение того, какая именно версия метода должна быть вызвана, основано на типе передаваемого аргумента.

Принципиальная значимость перегрузки состоит в том, что она позволяет обращаться к связанным методам посредством одного, общего для всех имени. Следовательно, имя Abs () представляет общее действие, которое выполняется во всех случаях. Компилятору остается правильно выбрать конкретную версию при конкретных обстоятельствах. А программисту нужно помнить лишь общую операцию, которая связана с именем того или иного метода. Благодаря полиморфизму применение нескольких имен сводится к одному. Несмотря на простоту приведенного примера, он все же позволяет понять, что перегрузка способна упростить процесс программирования.

 

 

Виртуальные методы. Функциональное назначение. Примеры применения.

Виртуальным называется метод, объявляемый с помощью ключевого слова virtual в базовом классе и переопределяемый в одном или нескольких производных классах. Таким образом, каждый производный класс может иметь собственную версию виртуального метода. Какую именно версию метода нужно вызвать, С# определяет по типу объекта, на который указывает эта ссылка, причем решение принимается динамически, во время выполнения программы. Следовательно, если имеются ссылки на различные объекты, будут выполняться различные версии виртуального метода. Другими словами, именно тип объекта, на который указывает ссылка (а не тип ссылки) определяет, какая версия виртуального метода будет выполнена. Чтобы объявить метод в базовом классе виртуальным, его объявление необходимо предварить ключевым словом virtual. При переопределении виртуального метода в производном классе используется модификатор override. Итак, процесс переопределения виртуального метода в производном классе иногда называется замещением метода (method overriding). При переопределении метода сигнатуры типа у виртуального и метода-заменителя должны совпадать. Кроме того, виртуальный метод нельзя определять как статический (с использованием слова static) или абстрактный (с использованием слова abstract).

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

Переопределение методов позволяет С# поддерживать динамический полиморфизм. Без полиморфизма объектно-ориентированное программирование невозможно, поскольку он позволяет исходному классу определять общие методы, которыми будут пользоваться все производные классы, и в которых при этом можно будет задать собственную реализацию некоторых или всех этих методов. Переопределенные методы представляют собой еще один способ реализации в С# аспекта полиморфизма, который можно выразить как "один интерфейс — много методов".

Пример:

class TwoDShape {

public virtual double area() { Console.WriteLine("Метод area() необходимо переопределить. " ) ;

return 0.0; }}

class Triangle : TwoDShape { // Класс треугольников, производный от класса TwoDShape

 

public override double area() { // Переопределяем метод аrеa() для класса Triangle

return width * height / 2 ; } }

class Rectangle : TwoDShape { // Класс прямоугольников, производный от класса TwoDShape

public override double area() {// Переопределяем метод аrеа() для класса Rectangle,

return width * height; } }

public static void Main() {

TwoDShape shape1 = new TwoDShape();

TwoDShape shape2 = new TwoDShape();

shape1= new Triangle();

shape2= new Rectangle(); }

Каждое переопределение метода area () реализует вариант вычисления площади, соответствующий типу объекта, инкапсулируемому производным классом.

Перегрузка операций. Функциональное назначение. Способ реализации. Примеры применения.

Под перегрузкой операции понимается существование нескольких реализаций одной и той же операции. Большинство операций языка C# перегружены - одна и та же операция может применяться к операндам различных типов. Поэтому перед выполнением операции идет поиск реализации, подходящей для данных типов операндов. Операции, как правило, выполняются над операндами одного типа. Если же операнды разных типов, то предварительно происходит неявное преобразование типа операнда.

Язык С# позволяет определить значение оператора относительно создаваемого класса. Этот процесс называется перегрузкой операторов. Перегружая оператор, вы расширяете его использование для класса. Результат действия оператора полностью находится в ваших руках, и может быть разным при переходе от класса к классу.

При перегрузке оператора ни одно из его исходных значений не теряется. Перегрузку оператора можно расценивать как введение новой операции для класса. Эта расширяемость типов — важная составляющая мощи таких объектно-ориентированных языков программирования, как С#. Если для класса определены некоторые операторы, вы можете оперировать объектами этого класса, используя обычный С#-синтаксис выражений. Более того, вы можете использовать в выражениях объект, включающий другие типы данных. Перегрузка операторов — одно из самых мощных средств языка С#. Перегрузка операторов тесно связана с перегрузкой методов. Для перегрузки операторов используется ключевое слово operator, позволяющее создать операторный метод, который определяет действие оператора, связанное с его классом. Существует две формы методов operator: одна используется для унарных операторов, а другая — для бинарных. Общий же формат (для обоих случаев) таков:

public static тип_возврата operator ор{ тип_параметра операнд)

{// операции}

// Общий формат перегрузки для бинарного оператора,

public static тип_возврата operator op{тип_параметра1 операнд1, тип_параметра2 операнд2) {// операции }

Здесь элемент ор — это оператор (например " + " или " / " ), который перегружается. Пример:

public static Rational operator +(Rational r1, Rational r2)

{ return (r1.Plus(r2)); }//метод Plus складывает дроби

 

16.Управление областями видимости членов класса. Функциональное назначение. Способ реализации. Примеры применения.

Исключительные ситуации. Понятие. Способы обработки исключительных ситуаций. Примеры применения.

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

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

Исключительная ситуация (или исключение) — это ошибка, которая возникает во время выполнения программы. Используя С#-подсистему обработки исключительных ситуаций, с такими ошибками можно справляться. Преимущество подсистемы обработки исключений состоит в автоматизации создания большей части кода, который ранее необходимо было вводить в программы "вручную". Обработка исключений упрощает "работу над ошибками", позволяя в программах определять блок кода, именуемый обработчиком исключение, который будет автоматически выполняться при возникновении определенной ошибки. В этом случае не обязательно проверять результат выполнения каждой конкретной операции или метода вручную. Если ошибка возникнет, ее должным образом обработает обработчик исключений. Еще одним преимуществом обработки исключительных ситуаций в С# является определение стандартных исключений для таких распространенных программных ошибок, как деление на нуль или попадание вне диапазона определения индекса. В С# исключения представляются классами. Все классы исключений должны быть выведены из встроенного класса исключений Exception, который является частью пространства имен System. Таким образом, все исключения — подклассы класса Exception.

С# определяет встроенные исключения, которые выводятся из класса SystemException. Например, при попытке выполнить деление на нуль генерируется исключение класса DivideByZeroException. Но можно создавать собственные классы исключений, выводя их из класса ApplicationException.

Основы обработки исключений

Ядром обработки исключений являются блоки try и catch. Эти ключевые слова работают "в одной связке"; нельзя использовать слово try без… t r y { // Блок кода, подлежащий проверке на наличие ошибок. } catch (ExcepType1 exOb) {// Обработчик для исключения типа ExcepTypel. }

Реализация интерфейсов

Если класс реализует интерфейс, он должен это сделать в полном объеме, т.е. реализация интерфейса не может быть выполнена частично. Классы могут реализовать несколько интерфейсов. В этом случае имена… class ByTwos : ISeries

Проблемы множественного наследования

При множественном наследовании классов возникает две основные проблемы — коллизия имен и наследование от общего предка.

Коллизия имен

Стратегия склеивания применяется тогда, когда класс — наследник интерфейсов — полагает, что разные интерфейсы задают один и тот же метод, единая… Другая стратегия исходит из того, что, несмотря на единую сигнатуру, методы… public interface Iprops

Наследование от общего предка

Для интерфейсов сама ситуация дублирующего наследования маловероятна, но возможна, поскольку интерфейс, как и любой класс, может быть наследником…   СИНТАКСИС ЯЗЫКА

Концепция типа данных. Соглашения о совместимости и приведение типов

1) множеством допустимых значений типа, 2) набором операций для этого типа, 3) диапазоном допустимых значений,

Концепция типа данных. Числовые типы данных.

1) множеством допустимых значений типа, 2) набором операций для этого типа, 3) диапазоном допустимых значений,

Концепция типа данных. Символьные типы данных.

1) множеством допустимых значений типа, 2) набором операций для этого типа, 3) диапазоном допустимых значений,

Структуры

{ public decimal price; public string title;

Концепция типа данных. Явное и неявное преобразование типов.

1) множеством допустимых значений типа, 2) набором операций для этого типа, 3) диапазоном допустимых значений,

Концепция типа данных. Определение собственных типов данных.

Создание нового класса с различными членами. Пример см. в «Основы программирования на C#» стр.154 ( Проектирование класса Rational). Программирование класса дробей как тип данных.

Концепция типа данных. Значащие (размерные) (Value type) и ссылочные (Reference type) типы данных. Упаковка и распаковка (Boxing, Unboxing).

1) множеством допустимых значений типа, 2) набором операций для этого типа, 3) диапазоном допустимых значений,

Принцип модульности программ. Глобальные и локальные имена. Область видимости имен. Выбор области видимости.

Переменные, которые объявляться на уровне модуля, называются глобальными. Их область действия распространяется, по крайней мере, на весь модуль. В… Переменные, объявленные на уровне процедуры, называются локальными, — они…  

Унарные и мультипликативные операции. Примеры применений.

Унарные: + - ! (логическое отрицание) ~ (поразрядное отрицание, инвертирует каждый разряд в двоичном представлении операнда типа int, uint, long, ulong) ++х --х (тип)х (преобразование типов).

Мультипликативные (умножения): * / % (остаток от деления)

Синтаксис объявления унарной операции: тип operator операция (параметр).

 

Аддитивные и сдвиговые операции. Примеры применений.

Аддитивные (сложения): + -

Сдвиг: << (влево) >> (вправо)

Общий формат записи этих операторов такой:

значение >> число битов; значение << число_битов.

Здесь значение — это объект операции сдвига, а элемент число_битов указывает, на сколько разрядов должно быть сдвинуто значение. При сдвиге влево на один разряд все биты, составляющее значение, сдвигаются влево на одну позицию, а в младший разряд записывается нуль. При сдвиге вправо все биты сдвигаются, соответственно, вправо. Если сдвигу вправо подвергается значение без знака, в старший разряд записывается нуль. Если же сдвигу вправо подвергается значение со знаком, значение знакового разряда сохраняется. При сдвиге как вправо, так и влево крайние биты теряются. Поскольку разряды представления двоичных чисел представляют собой степени числа 2, то операторы сдвига можно использовать в качестве быстрого способа умножения или деления чисел на 2. При сдвиге влево число удваивается. При сдвиге вправо число делится пополам. Конечно же, это будет справедливо до тех пор, пока с одного или другого конца не выдвинутся (и потеряются) значимые биты.

 

Принцип модульности программ. Метод, как отдельный модуль программы. Интерфейсная и скрытая часть метода. Формальные и фактические параметры метода. Примеры применения.

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

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

Процедуры и функции связываются теперь с классом, они обеспечивают функциональность данных класса и называются методами класса. Главную роль в программной системе играют данные, а функции лишь служат данным. Напомню здесь, что в C# процедуры и функции существуют только как методы некоторого класса, они не существуют вне класса.

Функция отличается от процедуры двумя особенностями:

• всегда вычисляет некоторое значение, возвращаемое в качестве результата функции;

• вызывается в выражениях.

Процедура C# имеет свои особенности:

• возвращает формальный результат void, указывающий на отсутствие результата;

• вызов процедуры является оператором языка;

• имеет входные и выходные аргументы, причем выходных аргументов может быть достаточно много.

Синтаксически в описании метода различают две части - описание заголовка и описание тела метода: заголовок_метода тело_метода

Рассмотрим синтаксис заголовка метода:

[атрибуты][модификаторы]{void| тип_результата_функции}

имя_метода([список_формальных_аргументов])

void A() {...}; int B(){...); public void C(){...};

Методы A и B являются закрытыми, а метод С - открыт. Методы A и С реализованы процедурами, а метод B - функцией, возвращающей целое значение.

Список формальных аргументов метода может быть пустым, и это довольно типичная ситуация для методов класса. Список может содержать фиксированное число аргументов, разделяемых символом запятой. [ref|out|params]тип_аргумента имя_аргумента

Несмотря на фиксированное число формальных аргументов, есть возможность при вызове метода передавать ему произвольное число фактических аргументов. Для реализации этой возможности в списке формальных аргументов необходимо задать ключевое слово params. Оно задается один раз и указывается только для последнего аргумента списка, объявляемого как массив произвольного типа. При вызове метода этому формальному аргументу соответствует произвольное число фактических аргументов.

Содержательно, все аргументы метода разделяются на три группы: входные (только читаются), выходные и обновляемые (их значения используются в ходе вычислений и обновляются в результате работы метода). Выходные аргументы всегда должны сопровождаться ключевым словом out, обновляемые - ref.

Между списком формальных и списком фактических аргументов должно выполняться определенное соответствие по числу, порядку следования, типу и статусу аргументов. Если в первом списке n формальных аргументов, то фактических аргументов должно быть не меньше n (соответствие по числу). Каждому i-му формальному аргументу (для всех i от 1 до n-1) ставится в соответствие i-й фактический аргумент. Последнему формальному аргументу, при условии, что он объявлен с ключевым словом params, ставятся в соответствие все оставшиеся фактические аргументы (соответствие по порядку). Если формальный аргумент объявлен с ключевым словом ref или out, то фактический аргумент должен сопровождаться таким же ключевым словом в точке вызова (соответствие по статусу).

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

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


 

Операции отношения и действий над типами данных. Примеры применений.

< > <= >= is (проверка принадлежности типу) as (приведение к типу)

С помощью оператора is можно определить, имеет ли рассматриваемый объект заданный тип. Общая форма его записи имеет следующий вид: выражение is ТИП

Здесь тип элемента выражение сравнивается с элементом ТИП. ЕСЛИ ТИП элемента выражение совпадает (или совместим) с элементом ТИП, результат выполнения операции принимается равным значению ИСТИНА. В противном случае — значению ЛОЖЬ.

Демонстрация выполнения оператора is:

class A {} class В : A {}

class Usels {

public static void Main() {

A a = new A () ; В b = new В();

if (a is A) Console.WriteLine("Объект а имеет тип A.");

if(b is A) Console.WriteLine("Объект b совместим с типом А, " + "поскольку его тип выведен из типа А.");

if(a is В) Console.WriteLine("Этот текст не будет отображен, " + "поскольку объект а не выведен из класса В.")

if(b is В) Console.WriteLine("Объект b имеет тип В."); if(a is object) Console.WriteLine("а — это объект."); }}

Иногда во время работы программы требуется выполнить операцию приведения типов, не генерируя исключение в случае, если попытка окажется неудачной. Для этого предусмотрен оператор as, формат которого таков: выражение as тип

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

Демонстрация использования оператора as:

class A {} class В : A {}

class CheckCast {

public static void Main() {

A a = new A(); В b = new В() ;

b = a as В; // Выполняем операцию приведения типов, если она возможна.

if(b==null)

Console.WriteLine("Операция приведения типов " + "b = (В) а НЕ РАЗРЕШЕНА.");

else Console.WriteLine( "Операция приведения типов b = (В) а разрешена.");

 

Логические операции. Примеры применений.

Логическое И (&), логическое исключающее ИЛИ (^), логическое ИЛИ ( | ).

Операторы перехода и оператор присваивания.

Операторов перехода, позволяющих прервать естественный порядок выполнения операторов блока, в языке C# несколько. Оператор goto: goto метка;

Инструкция goto — это С#-инструкция безусловного перехода. При ее выполнении управление программой передается инструкции, указанной с помощью метки. Инструкция goto требует наличие в программе метки. Метка — это действительный в С# идентификатор, за которым поставлено двоеточие. Метка должна находиться в одном методе с инструкцией goto, которая ссылается на эту метку. Например, с помощью goto можно организовать следующий цикл на 100 итераций: х = 1; loopl: //метка loopl, после кот. есть двоеточие

if(x < 100) goto loopl;

Операторы break и continue

Оператор break может стоять в теле цикла или завершать case-ветвь в операторе switch. При выполнении оператора break в теле цикла завершается выполнение самого внутреннего цикла. В теле цикла, чаще всего, оператор break помещается в одну из ветвей оператора if, проверяющего условие преждевременного завершения цикла.

Оператор continue используется только в теле цикла. В отличие от оператора break, завершающего внутренний цикл, continue осуществляет переход к следующей итерации этого цикла.

Оператор return

Еще одним оператором, относящимся к группе операторов перехода, является оператор return, позволяющий завершить выполнение процедуры или функции. Его синтаксис:

return выражение;

Возможны две формы использования инструкции return: одна предназначена для void-методов (которые не возвращают значений), а другая — для возврата значений. Немедленное завершение void-метода организовывается с помощью инструкции return: return;

При выполнении этой инструкции управление программой передается автору вызова метода, а оставшийся код опускается. Например:

public void myMethO { int i ; for(i=0; i<10; i++)

if ( i == 5) return; // Прекращение выполнения метода при i = 5.

16. Организация циклов в С#. Примеры применений.

Оператор for

For (инициализаторы; условие; список_выражений) тело цикла

Сколько раз будет выполняться тело цикла, зависит от трех управляющих элементов, заданных в скобках. Инициализаторы задают начальное значение одной или нескольких переменных, часто называемых счетчиками или просто переменными цикла. В большинстве случаев цикл for имеет один счетчик, но часто полезно иметь несколько счетчиков. Условие задает условие окончания цикла. Список выражений, записанный через запятую, показывает, как меняются счетчики цикла на каждом шаге выполнения. Если условие цикла истинно, то выполняется тело цикла, затем изменяются значения счетчиков и снова проверяется условие. Как только условие становится ложным, цикл завершает свою работу.

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

public bool Palindrom(string str)

{ for (int i =0, j =str.Length-1; i<j; i++,j--)

if(str[i]!=str[j]) return(false); return(true); }

Циклы While

While (выражение) оператор

Эта модификация соответствует стратегии: "сначала проверь, а потом делай". В результате проверки может оказаться, что и делать ничего не нужно. Тело такого цикла может ни разу не выполняться. Конечно же, возможно и зацикливание.

Цикл, проверяющий условие завершения в конце, соответствует стратегии: "сначала делай, а потом проверь". Тело такого цикла выполняется, по меньшей мере, один раз.

Цикл foreach

Цикл foreach, удобный при работе с массивами, коллекциями и другими подобными контейнерами данных. Его синтаксис: foreach(тип имя_переменной in коллекция) оператор

Здесь элементы тип и имя_переменной задают тип и имя итерационной переменной, которая при функционировании цикла fоreach будет получать значения элементов из коллекции. Элемент коллекция служит для указания опрашиваемой коллекции. Таким образом, элемент тип должен совпадать (или быть совместимым) с базовым типом массива.

int sum = 0; int [ ] nums = new int[10];

for (int i = 0; i < 10; i++)// Присваиваем элементам массива nums значения,

nums[i] - i;

foreach(int x in nums) {// отображение значений элементов массива и их суммирование

Console.WriteLine("Значение элемента равно: " + х); sum += х; }

Цикл работает в полном соответствии со своим названием — тело цикла выполняется для каждого элемента в массиве. Предполагается также, что элементы коллекции (массива, коллекции) упорядочены. На каждом шаге цикла переменная, задающая текущий элемент массива, получает значение очередного элемента в соответствии с порядком, установленным на элементах массива. С этим текущим элементом и выполняется тело цикла — выполняется столько раз, сколько элементов находится в коллекции. Цикл заканчивается, когда полностью перебраны все элементы коллекции. Серьезным недостатком циклов foreach в языке C# является то, что цикл работает только на чтение, но не на запись элементов.

 

Операторы условного перехода. Примеры применений.

Инструкция switch обеспечивает многонаправленное ветвление. Она позволяет делать выбор одной из множества альтернатив. Значение выражения последовательно сравнивается с константами из заданного списка. При обнаружении совпадения для одного из условий сравнения выполняется последовательность инструкций, связанная с этим условием. Общий формат записи инструкции switch такой: switch(выражение) {

case константа1:последовательность инструкций break;

case константа2:последовательность инструкций break;

default: последовательность инструкций break; }

Элемент выражение инструкции switch должен иметь целочисленный тип (например, char, byte, short или int) или тип string. Очень часто в качестве управляющего switch-выражения используется просто переменная; case-константы должны быть литералами, тип которых совместим с типом заданного выражения. При этом никакие две case-константы в одной switch-инструкции не могут иметь идентичных значений. Последовательность инструкций default-ветви выполняется в том случае, если ни одна из заданных case-констант не совпадет с результатом вычисления switch-выражения. Ветвь default необязательна. Если она отсутствует, то при несовпадении результата выражения ни с одной из case-констант никакое действие выполнено не будет. Если такое совпадение все-таки обнаружится, будут выполнены инструкции, соответствующие данной case-ветви до тех пор, пока не встретится инструкция break.

 

– Конец работы –

Используемые теги: Объектно-ориентированное, Программирование, Идеология, программирования, Технология, Достоинства, недостатки0.088

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

Что будем делать с полученным материалом:

Если этот материал оказался полезным для Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Еще рефераты, курсовые, дипломные работы на эту тему:

Оценка достоинств и недостатков высшего образования в Российской Федерации. Перспективы и сложности медицинского образования. Оценка достоинств и недостатков подготовки в ММА им. И.М.Сеченова.
К примеру, законом устанавливаются приоритетность области образования Гл.1,Ст.1 принципы государственная политики в области образования Гл1,Ст.2 1… Защита и развитие системой образования национальных культур, региональных… Автономность образовательных учреждений. задачи законодательства Российской Федерации в области образования 1…

Лекция 1. Объектно-ориентированное программирование – это новый подход к программированию. Объектно- ориентированные языки обладают свойством
ВВЕДЕНИЕ... Приступая к изучению более сложных конструкций языка С следует прежде всего повторить тот материал который был...

В первом семестре рассматриваются основные конструкции языка Си и базовая технология программирования структурное программирование
В первом семестре рассматриваются основные конструкции языка Си и базовая технология программирования структурное программирование... Структурное программирование это технология создания программ позволяющая... Компиляторы и интерпретаторы Трансляторы бывают...

Хозяйствующие формы бизнеса. Их достоинства и недостатки
Преимущества и недостатки. 4. Бесприбыльные фирмы 17 Глава 2. Развитие предпринимательства в Российской Федерации 19 Заключение: 23 Список… Существует 2 основных принципа организации экономической деятельности –… Примером стихийного порядка является рынок, где решения принимаются в ответ на изменение цен. Внутренняя организация…

Конспекты лекций По дисциплине Организация и технология обслуживания в барах для специальности 260501 Технология продуктов общественного питания
ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ... ВОРОНЕЖСКАЯ ГОСУДАРСТВЕННАЯ ТЕХНОЛОГИЧЕСКАЯ... Факультет среднего профессионального образования...

Методы линейного программирования, двойственность в линейном программировании
Методы линейного программирования двойственность в линейном... Задание Задание Задание...

Достоинства и недостатки плановой и рыночной экономики. Смешанный тип экономики
От типа системы зависит поведение государства, как на мировой, так и на внутренней арене. В своей курсовой работе я рассмотрю три типа экономических… Поэтому нам стоит познакомиться с особенностями основных таких систем и… Целью этой работы является анализ экономических систем. Какая всё-таки лучше? Так же я рассмотрю, к какому типу можно…

Объектно-ориентированное программирование на С с использованием библиотеки OpenGL
Диапазон вводимых значений программно ограничен, с целью недопущения некорректной работы или возникновения ошибки.Содержание. 1. Теоретическая часть… Актуальность разработки программного продукта, позволяющего оперировать с… Современное программное обеспечение предоставляет пользователю большое количество решений этой проблемы.

Постановка задачи линейного программирования и двойственная задача линейного программирования.
Всвязи с развитием техники, ростом промышленного производства и с появлением ЭВМвсе большую роль начали играть задачи отыскания оптимальных решений… Именно в силу этого процесс моделированиячасто носит итеративный характер. На… Здесь имеется полная аналогия с тем, как весьма важнаи зачастую исчерпывающая информация о поведении произвольной…

Компьютерные формы ведения бухучета, достоинства и недостатки
Ситуация такова, что сам по себе бухгалтерский учет на предприятии может рассматриваться как внутреннее дело предприятия, а основой для оценки… Кроме того, существуют плановые и внеплановые налоговые проверки, при… В условиях относительной неопределенности в налоговой сфере предприятие может сильно пострадать или даже потерпеть…

0.03
Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • По категориям
  • По работам