Спроектуємо клас для опису трикутників. Причому потрібно дати можливість клієнту ввести три сторони і отримати інформацію про периметр та площу.
Пишемо у клас Triangle, закриємо всі поля і методи, крім MyTriangle. Логічний метод Exists перевіряє існування трикутника.
Метод Exists обов’язково потрібно викликати у конструкторі.
Повний клас:
internal class Triangle
{
private Double a, b, c;
private bool isTriangle = false;
public Triangle(double a, double b, double c)
{
this.a = a;
this.b = b;
this.c = c;
if (this.Exist())
{
this.isTriangle = true;
}
}
private bool Exist()
{
return (a + b > c) && (a + c > b) && (b + c > a);
}
private Double Perimetr()
{
return this.a + this.b + this.c;
}
private Double Area()
{
double p = this.Perimetr() / 2;
return Math.Sqrt(p * (p - a) * (p - b) * (p - c));
}
public String MyTriangle()
{
Double S = this.Area();
Double P = this.Perimetr();
return (isTriangle)
? $"Трикутник зі сторонами {a}, {b}, {c}, \n площа = {S}, \n периметр = {P}"
: $"Трикутник зі сторонами {a}, {b}, {c} не існує.";
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyTriangle
{
class Program
{
static void Main(string[] args)
{
Triangle mytriangle1 = new Triangle(3, 4, 5);
Console.WriteLine(mytriangle1.MyTriangle());
Triangle mytriangle2 = new Triangle(300, 4, 5);
Console.WriteLine(mytriangle2.MyTriangle());
Console.ReadKey();
}
}
}

ЦЕ ЩЕ НЕ ВСЕ ПРО ІНКАПСУЛЯЦІЮ!!!
Якщо потрібен доступ до закритих полів класу — допоможуть методи доступу до полів (гетери, сетери), властивості (аксесори).
Якщо клієнт щось зламає, то захищений клас повідомить йому за допомогою механізму виключень, що він зробив не так і не дозволить "впасти проекту".
Зазвичай поля класу описують з модифікатором доступу privat. Цей модифікатор можна не писати, він встановлюється за умовчанням.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace triangle
{
class Triangle
{
private double a;
private double b;
private double c;
public Triangle(double x, double y, double z)
{
a = x;
b = y;
c = z;
}
public void Print()
{
Console.WriteLine("Сторони: a={0}, b={1}, c={2}", a, b, c);
}
}
}
Тому доступ до таких полів з інших класів неможливий. Будь-яка спроба прочитати значення з цього поля або записати щось, викликає помилку.
// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace triangle
{
class Program
{
static void Main(string[] args)
{
double x = 3, y = 4, z = 5;
Triangle t = new Triangle(x, y, z);
t.SetSideC(7); // Використовуємо метод для зміни сторони (замість прямого доступу до поля)
Console.WriteLine(t.GetSideC()); // Отримуємо значення сторони через метод
t.Print();
Console.ReadKey();
}
}
}
"triangle.Triangle.ct недоступний через рівень захисту" — виникає при спробі прямого доступу до приватного поля. Виправлено шляхом додавання методів-геттерів/сеттерів.
// Triangle.cs
namespace triangle
{
class Triangle
{
private double a;
private double b;
private double c; // Приватне поля (недоступні ззовні)
public Triangle(double x, double y, double z)
{
a = x;
b = y;
c = z;
}
// Методи для доступу до сторони 'c'
public double GetSideC() => c;
public void SetSideC(double value) => c = value;
public void Print()
{
Console.WriteLine($"Сторони: a={a}, b={b}, c={c}");
}
}
}
Але часто доступ до полів потрібний. Для цього використовуються властивості. Властивості ще називають методи аксесори.
Напишемо властивості для кожного поля цього класу.
class Triangle
{
private double a;
private double b;
private double c;
public Triangle(double x, double y, double z)
{
a = x;
b = y;
c = z;
}
// Властивість для сторони A
public double A
{
get { return a; }
set { a = value; }
}
// Властивість для сторони B
public double B
{
get { return b; }
set { b = value; }
}
// Властивість для сторони C
public double C
{
get { return c; }
set { c = value; }
}
}
Як бачимо, кожна властивість має заголовок і тіло.Відповідно до конвенцій C# — властивості називаються так само, як і поля, але з великої літери. У заголовку вказується модифікатор доступу (зазвичай public), тип значення, що повертається властивістю (у нас double) та ім'я властивості. Ім'я властивості таке саме як ім'я поля, якому воно відповідає, тільки починається з великої літери.
У тілі оголошено два методи get та set. Більше нічого в тілі якості оголошувати не можна. Метод get має ключове слово return та повертає будь-яке значення (зазвичай значення поля). Якщо цей метод є присутнім, то значення відповідного поля можна читати.
Метод set має ключове слово value і надає (встановлює) це значення полю об'єкта. Якщо цей метод є присутнім, то відповідному полю можна надавати значення.
У властивості може бути відсутнім get або set. Тоді поле буде лише для читання або лише для запису.
Описані вище властивості можна використовувати в іншому класі, і це не викликає жодної помилки. Звернення до властивості схоже на звернення до методу, тільки круглі дужки, як у методі, не пишуть.
class Program
{
static void Main(string[] args)
{
double x = 3, y = 4, z = 5;
Triangle t = new Triangle(x, y, z);
// Змінюємо сторону A через властивість
t.A = 7;
// Виводимо сторону C через властивість (замість прямого доступу до ct)
Console.WriteLine(t.C);
// Виводимо інформацію про трикутник
t.Print();
Console.ReadKey();
}
}
Властивості разом із модифікаторами доступу реалізують механізм захисту даних від несанкціонованого доступу.
Клас як тип, визначений користувачем, повинен містити:
Починаючи з версії C# 3.0, з’явилась можливість реалізувати дуже прості властивості без явного визначення змінної, якою керує властивість. Натомість базову змінну для властивості автоматично створює компілятор. Такі властивості називають автоматично реалізованими і вони мають наступну загальну форму:
тип ім'я { get; set; }
де тип позначає конкретний тип властивості, а ім'я — ім'я властивості. Зверніть увагу, що після get і set йде крапка з комою, а тіла відсутні. Цей синтаксис наказує компілятору створити автоматичну змінну, яку іноді називають полем підтримки, для збереження значення. Ця змінна недоступна напряму і не має імені, але доступна через властивість.
У чому перевага автосвойств, якщо вони по суті просто звертаються до автоматично створеної змінної? Чому б не звертатися напряму до змінної без автосвойств? Справа в тому, що в будь-який момент при необхідності ми можемо розгорнути автосвойство у звичайне, додати у нього певну логіку.
Варто враховувати, що неможливо створити автоматичну властивість тільки для запису, як у випадку зі стандартними властивостями.
internal class Triangle
{
public double A { get; private set; }
public double B { get; private set; }
public double C { get; private set; }
public double Perimeter
{
get { return A + B + C; }
}
public double Area
{
get
{
double p = Perimeter / 2;
return Math.Sqrt(p * (p - A) * (p - B) * (p - C));
}
}
private bool Exist()
{
return (A + B > C) && (A + C > B) && (B + C > A)
&& (A> 0) && (B > 0) && (C > 0);
}
public Triangle(double a, double b, double c)
{
A = a;
B = b;
C = c;
if (!Exist())
throw new Exception("Трикутник з такими сторонами не існує");
}
}
using System;
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Введіть три сторони трикутника:");
double a = Convert.ToDouble(Console.ReadLine());
double b = Convert.ToDouble(Console.ReadLine());
double c = Convert.ToDouble(Console.ReadLine());
Console.WriteLine($"Конструктор з трьома параметрами. Три сторони трикутника: {a}, {b}, {c}.");
Triangle mytriangle = new Triangle(a, b, c);
Console.WriteLine($"Периметр = {mytriangle.Perimeter}");
Console.WriteLine($"Площа = {mytriangle.Area}");
Console.WriteLine("Введіть три сторони трикутника:");
a = Convert.ToDouble(Console.ReadLine());
b = Convert.ToDouble(Console.ReadLine());
c = Convert.ToDouble(Console.ReadLine());
Triangle mytriangle2 = new Triangle(a, b, c);
Console.WriteLine($"Конструктор з трьома параметрами. Три сторони трикутника: {mytriangle2.A}, {mytriangle2.B}, {mytriangle2.C}.");
Console.WriteLine($"Периметр = {mytriangle2.Perimeter}");
Console.WriteLine($"Площа = {mytriangle2.Area}");
}
catch
{
Console.WriteLine("Трикутник не існує.");
}
}
}
