Объектно-ориентированное программирование

Объекты в программировании

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

Функции, определяемые в объекте, называются методами объекта и определяют его поведение или изменение его свойств.

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

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

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

Значения атрибутов объекта определяют состояние объекта, а методы, изменяя значения атрибутов, определяют поведение объекта, т.е. изменение его состояния.

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

using System;

namespace Objects
{
    class Person
    {
        public string firstName, familyName, fatherName;
        public DateTime birthday;


        public string FullName()
        {
            string temp;
            temp = familyName + " " + firstName + " ";
            temp += fatherName;
            return temp;
        }
        public string ShortName()
        {
            string temp;
            temp = familyName + " " + firstName[0] + ". ";
            temp += fatherName[0] + ".";
            return temp;
        }
        public int nmbYears()
        {
            int temp;
            DateTime now = DateTime.Now;
            temp = now.Year - birthday.Year;
            if (now.Month > birthday.Month)
                temp--;
            else if ((now.Month == birthday.Month)
                        && (now.Day > birthday.Day)) temp--;
            //if (new DateTime(now.Year, birthday.Month, birthday.Day) < now) temp--;
            return temp;
        }
    }
}

Работа с объектом иллюстрируется следующей простой программой

using System;

namespace Objects
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            p.familyName = "Иванов";
            p.firstName = "Иван";
            p.fatherName = "Иванович";
            p.birthday = new DateTime(2000, 3, 28);
            Console.WriteLine(p.FullName());
            Console.WriteLine(p.ShortName());
            Console.WriteLine("Число полных лет - {0}", p.nmbYears());
            
        }
    }
}

Следующий пример иллюстрирует работу с набором однотипных объектов

        static void Example_2()
        {
            ArrayList persons = new ArrayList();//Требуется System.Collections
            Person[] ar_pers = new Person[0];
            //Console.WriteLine(ar_pers.Length);
            string s = "";
            do
            {
                Person p = new Person();
                int y, m, d;
                Console.WriteLine("Введите личные данные");
                Console.Write("Фамилия: ");
                s = Console.ReadLine();
                p.FamilyName = s;
                Console.Write("Имя: ");
                s = Console.ReadLine();
                p.FirstName = s;
                Console.Write("Отчество: ");
                s = Console.ReadLine();
                p.FatherName = s;
                Console.WriteLine("Введите дату рождения");
                Console.Write("Год в четырехзначном формате: ");
                y = int.Parse(Console.ReadLine());
                Console.Write("Номер месяца: ");
                m = int.Parse(Console.ReadLine());
                Console.Write("Число: ");
                d = int.Parse(Console.ReadLine());
                p.Birthday = new DateTime(y, m, d);
                persons.Add(p);
                Array.Resize(ref ar_pers, ar_pers.Length + 1);
                ar_pers[ar_pers.Length - 1] = p;
                Console.WriteLine("Чтобы закончить ввод нажмите клавишу \"д\" или \"Д\"");
                s = Console.ReadLine();
            }while(!((s=="д")||(s=="Д")));
            foreach(Person p in persons)
            {
                Console.WriteLine(p.FullName() + " " + p.Birthday.Year + " " +
                    p.Birthday.Month + " " + p.Birthday.Day);
            }
            foreach (Person p in ar_pers)
            {
                Console.WriteLine(p.FullName() + " " + p.Birthday.Year + " " +
                    p.Birthday.Month + " " + p.Birthday.Day);
            }
        }

Следующий пример демонстрирует возможности сохранения информации в файле для последующего создания объектов

        static void Example_3()
        {
            FileStream fs = new FileStream("persons.txt", FileMode.OpenOrCreate);
            StreamWriter writer = new StreamWriter(fs);
            string s, line;
            do
            {
                int y, m, d;
                line = "";
                Console.WriteLine("Введите личные данные");
                Console.Write("Фамилия: ");
                s = Console.ReadLine();
                line += s + '\t';
                Console.Write("Имя: ");
                s = Console.ReadLine();
                line += s + '\t';
                Console.Write("Отчество: ");
                s = Console.ReadLine();
                line += s + '\t';
                Console.WriteLine("Введите дату рождения");
                Console.Write("Год в четырехзначном формате: ");
                s = Console.ReadLine();
                y = int.Parse(s);
                line += s + '\t';
                Console.Write("Номер месяца: ");
                s = Console.ReadLine();
                m = int.Parse(s);
                line += s + '\t';
                Console.Write("Число: ");
                s = Console.ReadLine();
                d = int.Parse(s);
                line += s;
                writer.WriteLine(line);
                Console.WriteLine("Чтобы закончить ввод нажмите клавишу \"д\" или \"Д\"");
                s = Console.ReadLine();
            } while (!((s == "д") || (s == "Д")));
            if(writer != null) writer.Close();
        }

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

        static void Example_4()
        {
            FileStream fs = new FileStream("persons.txt", FileMode.Open);
            StreamReader reader = new StreamReader(fs);
            string line = reader.ReadLine();
            ArrayList persons = new ArrayList();//Требуется System.Collections
            while (line != null)
            {
                string[] strings = line.Split('\t');
                Person p = new Person();
                int y, m, d;
                p.FamilyName = strings[0];
                p.FirstName = strings[1];
                p.FatherName = strings[2];
                y = int.Parse(strings[3]);
                m = int.Parse(strings[4]);
                d = int.Parse(strings[5]);
                p.Birthday = new DateTime(y, m, d);
                persons.Add(p);
                line = reader.ReadLine();
            }
            foreach (Person p in persons)
            {
                Console.WriteLine(p.FullName() + " " + p.Birthday.Year + " " +
                    p.Birthday.Month + " " + p.Birthday.Day);
            }
        }

В следующем примере показывается пример наследования объектов и использование полиморфизма. Полиморфизмом называется способность двух или более объектов различных классов отвечать на вызов одного и того же метода различным образом в зависимости от специфики объекта. В данном случае объекты Student и Teacher наследуются от объекта Person и при вызове метода ShortName() выдают разную информацию, отвечающую специфике объекта.

    class Person
    {
        private string firstName, familyName, fatherName;
        private DateTime birthday;

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }
        public string FamilyName
        {
            get { return familyName; }
            set { familyName = value; }
        }
        public string FatherName
        {
            get { return fatherName; }
            set { fatherName = value; }
        }
        public DateTime Birthday
        {
            get { return birthday; }
            set { birthday = value; }
        }

        public virtual string FullName()
        {
            string temp;
            temp = familyName + " " + firstName + " ";
            temp += fatherName;
            return temp;
        }
        public virtual string ShortName()
        {
            string temp;
            temp = familyName + " " + firstName[0] + ". ";
            temp += fatherName[0] + ".";
            return temp;
        }
        public int nmbYears()
        {
            int temp;
            DateTime now = DateTime.Now;
            temp = now.Year - birthday.Year;
            if (now.Month > birthday.Month)
                temp--;
            else if ((now.Month == birthday.Month)
                        && (now.Day > birthday.Day)) temp--;
            //if (new DateTime(now.Year, birthday.Month, birthday.Day) < now) temp--;
            return temp;
        }
    }
    class Student:Person
    {
        public string Faculty;
        public string Group;
        public override string ShortName()
        {
            string temp;
            temp = base.ShortName();
            temp += " Факультет: " + Faculty + " Группа: " + Group;
            return temp;
        }
    }
    class Teacher:Person
    {
        public string Cathedra;

        public override string ShortName()
        {
            string temp;
            temp = base.ShortName();
            temp += " Кафедра: " + Cathedra;
            return temp;
        }
    }
        static void Example_5()
        {
            Student st1 = new Student();
            st1.FamilyName = "Иванов";
            st1.FirstName = "Иван";
            st1.FatherName = "Иванович";
            st1.Faculty = "Информатика";
            st1.Group = "41/1";
            Console.WriteLine(st1.FullName());
            Teacher te1 = new Teacher();
            te1.FamilyName = "Петров";
            te1.FirstName = "Петр";
            te1.FatherName = "Петрович";
            te1.Cathedra = "Информатика и вычислительная техника";
            Console.WriteLine(te1.FullName());
            ArrayList persons = new ArrayList();//Требуется System.Collections
            persons.Add(te1);
            persons.Add(st1);
            foreach (Person p in persons)
            {
                Console.WriteLine(p.ShortName());
            }
        }

Важным примером наследования является наследование от абстрактных классов. Абстрактным называется класс, в котором имеется хотя бы один нереализованный метод, как, например, в следующем примере абстрактный класс Shape, имеющий метод calcArea(), реализация которого не задана. Этот метод реализуется только в классах производных от класса Shape

    public abstract class Shape
    {
        public abstract double calcArea();
    }
    public class Rectangle : Shape
    {
        private double length;
        private double width;
        public Rectangle(double l, double w)
        {
            length = l;
            width = w;
        }
        public override double calcArea()
        {
            return length * width;
        }
    }
    public class Circle : Shape
    {
        private double radius;
        public Circle(double r)
        {
            radius = r;
        }
        public override double calcArea()
        {
            return Math.PI * radius * radius;
        }
    }
        static void Example_6()
        {
            Rectangle r = new Rectangle(3, 4);
            Circle c = new Circle(5);
            Console.WriteLine("Площадь: {0:f1}", r.calcArea());
            Console.WriteLine("Площадь: {0:f1}", c.calcArea());
        }
Hosted by uCoz