Близнюки (шаблон проєктування)
Близнюки — патерн проєктування, що дозволяє імітувати множинне наслідування у мовах програмування, які цього не підтримують.
Опис[ред. | ред. код]
Нехай дано два класи, які потрібно успадкувати
public class ListBox { public virtual void Render() { System.Console.WriteLine("Render list box"); } } public class UserCollection { public virtual void GetUsers() { System.Console.WriteLine("Return collection of users"); } }
Тоді у батьківському класі реалізуємо класи спадкоємці як внутрішні класи:
public class UserListBox { private readonly string _callerName = "UserListBox"; // батьківський клас містить посилання на кожного із нащадків private readonly InnerUserCollection _userCollection; public UserListBox() { _userCollection = new InnerUserCollection(this); } // батьківський клас реалізовує поведінку всіх класів, що наслідує public static implicit operator UserCollection(UserListBox userListBox) => userListBox._userCollection; private class InnerUserCollection : UserCollection { // кожний спадкоємець містить посилання на батьківський клас private readonly UserListBox _parent; public InnerUserCollection(UserListBox parent) { this._parent = parent; } public override void GetUsers() { // доступ до приватних членів батьківського класу System.Console.WriteLine(_parent._callerName); base.GetUsers(); } } }
Реалізація[ред. | ред. код]
C#[ред. | ред. код]
namespace TwinPattern { // класи для наслідування public class ListBox { public virtual void Render() { System.Console.WriteLine("Render list box"); } } public class UserCollection { public virtual void GetUsers() { System.Console.WriteLine("Return collection of users"); } } // наслідування класів відбувається через реалізацію "близнюків" public class UserListBox { private readonly string _callerName = "UserListBox"; private readonly InnerUserCollection _userCollection; private readonly InnerListBox _listBox; public UserListBox() { _userCollection = new InnerUserCollection(this); _listBox = new InnerListBox(this); } // "наслідування" декількох класів public static implicit operator UserCollection(UserListBox userListBox) => userListBox._userCollection; public static implicit operator ListBox(UserListBox userListBox) => userListBox._listBox; private class InnerUserCollection : UserCollection { private readonly UserListBox _parent; public InnerUserCollection(UserListBox parent) { this._parent = parent; } public override void GetUsers() { System.Console.WriteLine(_parent._callerName); base.GetUsers(); } } private class InnerListBox : ListBox { private readonly UserListBox _parent; public InnerListBox(UserListBox parent) { this._parent = parent; } public override void Render() { System.Console.WriteLine(_parent._callerName); base.Render(); } } } class Program { static void RenderListBox(ListBox listBox) { listBox.Render(); } static void GetUsers(UserCollection userCollection) { userCollection.GetUsers(); } static void Main(string[] args) { UserListBox userListBox = new UserListBox(); // "наслідування" декількох класів RenderListBox(userListBox); GetUsers(userListBox); } } }