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

Текущий объект, this

 

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

Как иллюстрацию этого включим в класс class CLUgli из примера 5.3 конструктор с параметрами, в котором будем заполнять поля с длинами сторон треугольника только в том случае, если эти данные корректны, то есть сумма длин двух сторон больше третьей. Кроме этого заведем поле типа bool, в котором будем хранить результат этой проверки.

Исходный текст данного класса приведен в примере 6.2. На что здесь надо обратить внимание? Конструкторов пришлось делать два: один с параметрами, а еще один без параметров. Почему? В C# сделали так: если конструктора в классе нет, то вызывается конструктор по умолчанию, но если хотя бы один конструктор есть, то никаких умолчаний, все нужно описывать в явном виде. И еще, здесь используется служебное слово this, за которым скрывается текущий объект, то есть тот объект, с которым работает данный метод в данный момент времени. Для чего это сделано? В этом примере для того, чтобы не путать параметры метода a,b,c и поля объекта a,b,c.

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

Пример 6.2

class CLUgli

   {

       public double a, b, c;

       public double ua, ub, uc;

       public bool ok = true;// для проверки корректности

           

       public CLUgli(double a, double b, double c)

       //конструктор с параметрами

       {

           if (a + b > c && a + c > b && b + c > a)

           {

               this.a = a;

               this.b = b;

               this.c = c;

           }

           else

               this.ok = false;

       }

       public CLUgli() //конструктор без параметров

       {

       }

       public double ugol(double a, double b, double c)

       {

           double aa;

           aa = (b * b + c * c - a * a) / (2 * b * c);

           aa = Math.Acos(aa);

           aa = Rad_v_Drad(aa); //новое

           return aa;

       }

 

       private double Rad_v_Drad(double x) //новое

       {

             return 180 * x / Math.PI;

       }

}

Для демонстрации работы с таким конструктором заведем на форме еще одну кнопку. Читать данные и скидывать результаты будем в те же редакторы, но если данные некорректны, будем сообщать об этом. Текст обработчика события Click кнопки button3 приведен в примере 6.3.  Остальной текст файла Form1.cs не изменится.

Пример 6.3

   private void button3_Click(object sender, EventArgs e)

   {

       double a = Convert.ToDouble(textBox1.Text);

       double b = Convert.ToDouble(textBox2.Text);

       double c = Convert.ToDouble(textBox3.Text);

       CLUgli ugli2 = new CLUgli(a,b,c);

       if (ugli2.ok)

       {

          ugli2.ua = ugli2.ugol(ugli2.a, ugli2.b, ugli2.c);

            ugli2.ub = ugli2.ugol(ugli2.b, ugli2.a, ugli2.c);

            ugli2.uc = ugli2.ugol(ugli2.c, ugli2.a, ugli2.b);

           textBox4.Text = Convert.ToString(ugli2.ua);

           textBox5.Text = Convert.ToString(ugli2.ub);

           textBox6.Text = Convert.ToString(ugli2.uc);

       }

       else

       {

           string s = "Данные не корректны";

           textBox4.Text = s;

           textBox5.Text = s;

           textBox 6. Text = s ;

       }

   }

}

 

Запустите приложение на выполнение. Если данные корректные, то результаты одинаковые при работе с обоими конструкторами, но если данные некорректные, то результаты отличаются. Это иллюстрируется на рис. 6.4, 6.5, 6.6.

 

 

Рис. 6.4. Результаты работы программы из примера 6.3

 

 

Рис. 6.5. Результаты работы программы из примера 6.3

 

 

Рис. 6.6. Результаты работы программы из примера 6.3

 

 

Закрытые поля, свойства

 

Ну и последнее из обещанного ранее.

До этого писали классы с открытыми полями, а методы писали как открытыми (public), так и закрытыми (private). Оказывается, с открытыми полями никто не работает. Это плохое программирование. Поля должны быть закрытыми. Этого требуют условия безопасности приложения. Получается, что доступ к полям возможен только через методы класса, и для доступа к данным используется конструкция языка, которая называется свойством. Свойство состоит из двух методов со стандартными именами get и set. Свойство можно понимать как интеллектуальные поля, поддерживающие инкапсуляцию класса. С точки зрения практического применения свойство доступно так же, как открытое поле в классе. Единственным ограничением является то, что свойство не может передаваться в метод как параметр. Можно рассуждать так: между пользователем (вызовом данных) и данными ставят посредника, который называется свойством. Этот посредник может быть наделен некоторыми контрольными и демпферными особенностями.

Как это делается практически.

 Есть закрытое поле

private double a;

Объявляют свойство

public double A

   {

       get { return a; }

       set { a = value; }

   }

Свойство типа double с именем A объявлено открытым. В C# принято поля именовать с маленькой буквы, а соответствующие им свойства с большой. За именем в фигурных скобках пишутся аксессоры ( accessor ) – get и set. Они указывают доступ свойства к полю на чтение ( get ) и запись    ( set ). После имени аксессора в фигурных скобках указываются действия свойства.

В примере в аксессоре get записано – возвратить значение поля a , в аксессоре setполю a присвоено значение виртуальной переменой value. Почему виртуальной? Потому что она нигде не объявлена, но всегда существует внутри set и имеет тот же тип и значение, что и свойство. В итоге, в нашем случае свойство это просто обертка для поля. Да, но она соответствует принципам безопасности.

В сквозном примере про треугольник можно написать так:

public double A

   {

       get{ return a;}

       set{// можно контролировать установку

           if (value > 0)

               a = value;

           else

               ok = false;

          }

   }

Здесь в свойстве выставлен контроль на запись.

А можно так:

public double Ua

   {

       get { return ua; }

   }

Здесь свойство Ua доступно только для чтения, потому что аксессора set нет.

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

public bool Ok { get; set; } Тогда Ok будет и свойством для внешних источников, и полем для внутреннего использования.

В итоге код предыдущего примера 6.3 будет выглядеть так (пример 6.4).

Пример 6.4.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

Дата: 2019-11-01, просмотров: 178.