Модул 5. Обектно-ориентирано програмиране
Материали | Задачи | Решения | Видео
Съдържание
Unit Testing
Get started with unit testing: https://docs.microsoft.com/en-us/visualstudio/test/getting-started-with-unit-testing?view=vs-2019
Visual Studio Team Tests (VSTT)
[TestClass]
public class TheClassName
{
[TestMethod]
public void TheTestName()
{
...
AAA = Arrange + Act + Assert
[TestMethod]
public void DespositMoneyTest()
{
// Arrange
BankAccount bank = new BankAccount();
// Act
bank.Deposit(50);
// Assert
Assert.IsTrue(bank.Balance == 50);
}
Atributes
[TestClass] = denotes a class holding unit tests
[TestMethod] = denotes a unit test method
[ExpectedException] = test causes an exception
[Timeout] = sets a timeout for test execution
[Ignore] = temporary ignored test case
[ClassInitialize], [ClassCleanup] = setup / cleanup logic for the testing class
[TestInitialize], [TestCleanup] = setup / cleanup logic for each test case
Asserts
AreEqual(expected value, calculated value [,message]) = compare two values for equality
AreSame(expected object, current object [,message]) = compare object references
IsNull(object [,message])
IsNotNull(object [,message])
IsTrue(condition)
IsFalse(condition)
Fail(message) = Forced test fail
Зависимости
Добрa практики за избягване на взаимообвързване на класовете е използването на интерфейсти.
Интерфейсите са договор, който показва, че дадения клас който наследява интерфейса е задължен да има съответната функционалност.
Имитиране на обекти
Userfull Reading:
Шаблони
class List<T>
{
public Add (T element) { ... }
public T Remove () { ... }
public T { get; }
}
Интерфейси
interface IBox<T>
{
void Add (T element);
...
}
class MyList<T> : IBox<T> { ... }
Ограничители
Ограничаване до референтен тип
public void MyMethod<T>() where T : class
Ограничаване до примитивен тип
public void MyMethod<T>() where T : struct
Ограничаване до конструктор
public void MyMethod<T>() where T : new ()
Ограничаване до статичен базов клас
public void MyMethod<T>() where T : BaseClass
Ограничаване до шаблонен базов клас
public void MyMethod<T,U>() where T : U
Наследяване
Наследяващият клас получава всички членове от родителския си клас.
class Person { ... }
class Student : Person { ... }
Конструкторите не се наследяват, но може да се използват.
public Student(String name, School school) : base(name) { ... }
Подкласовете наследават данните с модификатори за достъп (public) и (protected), но не и тези с (private).
this.weight; // Достъп до член от тази инстанция
base.weight; // Достъп до член от базовия клас
Виртуалнита методи позволяват пренаписване.
public class Animal
{
public virtual void Eat() { ... }
}
public class Dog : Animal
{
public override void Eat() { ... }
}
Абстракция и интерфейси
Абстракцията се постига чрез интерфейси и абстрактни класове и представлява процес на скриване на подробностите на имплементацията и показване само на функционалностите към потребителя.
public interface IAnimal {}
public abstract class Mammal {}
public class Person : Mammal, IAnimal {}
Класът може да наследи само един абстрактен клас.
Класът може да имплементира няколко интерфейса.
Абстрактните класове могат да предоставят целия код и/или само детайлите, които трябва да се презапишат.
Интерфейсът не може да предоставя никакъв код, предоставя само описание.
Абстрактния клас може да съдържа модификатори за достъп
Интерфейсите нямат модификатори за достъп. Всичко е публично по подразбиране.
Ако множество имплементации са от сходен вид и имат общо поведение или статут, то абстрактния клас е по-добър избор.
Ако множество имплементации споделят само сигнатурата на методите и нищо друго, то тогава интерфейсът е по-добър избор.
Абстрактният клас може да притежава полета и константи
Не поддържа полета
Ако добавим нов метод към абстрактен клас, то имаме опцията да създадем имплементация по подразбиране и така съществуващият код ще може да работи коректно.
Ако добавим нов метод към интерйфес, то трябва да проследим всичките му имплементации и да дефинираме имплементация за новия метод.
Презареждане (overloading)
Методи с едно и също име, но различни сигнатури.
public int Add(int a, int b)
public double Add(double a, double b, double c)
public decimal Add(decimal a, decimal b, decimal c)
Презаписване (overriding)
Създаване на метод със същото име и сигнатура в подклас.
public class Person
{
public virtual string IntroduceYourself() { ... }
}
public class Student : Person
{
public override string IntroduceYourself() { ... }
}
Итератори
IEnumerable
Интерфейс за обхождане на колекция
public interface IEnumerable<T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
IEnumerator
Предоставя последователно, еднопосочно обхождане на колекция от произволен тип
public interface IEnumerator<T> : IEnumerator
{
bool MoveNext();
void Reset();
T Current { get; }
}
public interface IEnumerator
{
bool MoveNext();
void Reset();
object Current { get; }
}
MoveNext() = премества итератора към следваща позиция
Reset() = връща итератора на начална позиция
Current = връща елемента от колекцията на текущата позиция на итератора
Компаратори
IComparable
class Point : IComparable<Point>
{
public int CompareTo(Point otherPoint)
{
...
}
}
IComparer
class CatComparer : IComparer<Cat>
{
public int Compare(Cat x, Cat y)
{
...
}
}
Отражение на типове (Reflection)
Техника на програмиране, при която компютърни програми мога да третират други програми като свои данни.
Type
Основен начин за достъп до метаданните.
Type myType = typeof(ClassName);
Name
Предоставя името на класа.
string fullName = typeOf(SomeClass).FullName;
string simpleName = typeOf(SomeClass).Name;
Class and Interface
Type baseClassType = testClass.BaseType;
Type[] classInterfaces = testClass.GetInterfaces();
CreateInstance
Създава екземпляр от класа чрез извикване на конструктора, който най-добре пасва на указаните параметри.
Type sbType = Type.GetType("System.Text.StringBuilder");
StringBuilder sbInstance = (StringBuilder) Activator.CreateInstance(sbType);
StringBuilder sbInstCapacity = (StringBuilder)Activator.CreateInstance(sbType, new object[] {10});
Fields
Предоставя публичните полета
FieldInfo field = type.GetField("name"); FieldInfo[] publicFields = type.GetFields();
Предоставя всички полета
FieldInfo[] allFields = type.GetFields(
BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Field Type
Получаване на името и типа на полето
FieldInfo field = type.GetField("fieldName");
string fieldName = field.Name;
Type fieldType = field.FieldType;
Access Modifiers
field.IsPrivate // частен
field.IsPublic // публичен
field.IsNonPublic // не е публичен
field.IsFamily // защитен (protected)
field.IsAssembly // вътрешен (internal)
Constructors
ConstructorInfo[] publicCtors = type.GetConstructors();
Create New Object Instances
StringBuilder builder = (StringBuilder)constructor.Invoke(new object[] params);
Methods
MethodInfo[] publicMethods = sbType.GetMethods();
Достъп до параметрите на метод и връщания тип данни
ParameterInfo[] appendParameters = appendMethod.GetParameters();
Type returnType = appendMethod.ReturnType;
Извиква методи
appendMethod.Invoke( builder, new object[] { "hi!" });
Функционално програмиране
Lambda Expressions
msg => Console.WriteLine(msg);
(String msg) => { Console.WriteLine(msg); }
() => { Console.WriteLine("hi"); }
(int x, int y) => { return x + y; }
Lambda Functions
x => x / 2
static int Func(int x) { return x / 2; }
x => x != 0
static bool Func(int x) { return x != 0; }
() => 42
static int Func() { return 42; }
(x, y) => x+y
static int Func(int x, int y) { return x+y; }
LINQ & Collections
ToArray(), ToList()
Select(), Where(), OrderBy()
Min(), Max(), Sum(), Average(), Count()
First(), Last() , Single()
Skip(), Take()
Distinct()
Reverse()
Concat()
Изключения (Exception)
Прихващане на изключенията
try
{
...
}
catch (Exception)
{
...
}
finally
{
...
}
Типове
System.ArgumentException
System.FormatException
System.NullReferenceException
System.OutOfMemoryException
System.StackOverflowException
Хвърляне на изключения
throw new ArgumentException("Invalid amount!");
Типове
ArgumentException
ArgumentNullException
ArgumentOutOfRangeException
NotSupportedException
NotImplementedException
Потоци (Streams)
Четене от файл
StreamReader reader = new StreamReader("filename.txt");
string line = reader.ReadLine();
Запис във файл
StreamWriter writer = new StreamWriter("filename.txt");
reader.WriteLine("Hello World");
Стандартни потоци
File Stream
var fileStream = new FileStream("filename.txt",FileMode.Create);
byte[] bytes = Encoding.UTF8.GetBytes(text);
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Close();
Memory Stream
var memoryStream = new MemoryStream(bytes)
int readByte = memoryStream.ReadByte();
Network Stream
var tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 22);
tcpListener.Start();
NetworkStream stream = tcpListener.AcceptTcpClient().GetStream();
byte[] request = new byte[1024];
stream.Read(request, 0, request.Length);
Console.WriteLine(Encoding.UTF8.GetString(request));
byte[] response = Encoding.UTF8.GetBytes("Hello World");
stream.Write(response, 0, response.Length);
Last updated
Was this helpful?