Сообщество - Лига программистов
Добавить пост

Лига программистов

1 514 постов 11 410 подписчиков

Популярные теги в сообществе:

Инкапсуляция и Наследование

Штош, Пикабу явно хочет поговорить про ооп. Так не будем останавливаться. Тем более, что в комментариях уже предложили массу тем для будущих постов. В этот раз я постараюсь описать принципы инкапсуляции и наследования и надеюсь, что более опытные коллеги смогут дать мне дельные советы и по этому поводу.


Инкапсуляция и Наследование Опрос, PHP, Программирование, Ооп, Oop, Длиннопост

Примеры все еще на PHP

Инкапсуляция

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

В прошлый раз я остановился на классе Текст. Сейчас я внесу в него изменения и, возможно, он станет лучше. К сожалению, у меня в редакторе нет возможности оформить код более красиво. Но, зато его можно скопировать в песочницу и попробовать выполнить.

<?php

class Text {

private $text;

public function __construct($text){

$this->text = $text;

}

public function printText() {

echo $this->text;

}

}

$hello = new Text("Hello, "); // создаем объект hello

$world = new Text("World!"); // создаем объект world

$hello->printText(); // вызываем метод print объекта hello

$world->printText(); // вызываем метод print объекта world

echo PHP_EOL.get_class($hello); // проверяем класс

echo PHP_EOL.get_class($world); // проверяем класс

?>

Здесь я добавил конструктор класса. С его помощью я передаю параметр с текстом. Этот параметр записывается в свойство text. Перед объявлением свойства text я использовал ключевое слово private, которое запрещает доступ к свойству извне класса. Функция get_class возвращает имя класса. Здесь я проверю, что класс двух объектов совпадает, почему это важно? Узнаем в следующих постах.

Определение возможности доступа к свойствам и методам класса (public, private, protected) - это сокрытие.

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

Наследование

Итак, у нас есть класс, который принимает параметр и печатает текст. В нашем проекте нужно печатать текст в двух стилях. Заголовки, которые будут написаны капсом и обычные строки, у которых только первая буква будет большой. Мы можем написать функции для каждого случая обработки строк. Можем написать разные классы. Или можем использовать уже готовый класс и расширить его возможности. Напишу еще пару классов.

<?php

class Text {

protected $text;

public function __construct($text){

$this->text = $text;

}

public function printText() {

return $this->text;

}

}

class Header extends Text {

public function printText() {

return strtoupper($this->text);

}

}

class Sentence extends Text {

public function printText() {

return ucfirst(strtolower($this->text));

}

}

$header = new Header("hello, world!");

$sentence = new Sentence("hello, WORLD!");

echo $header->printText();

echo PHP_EOL;

echo $sentence->printText();

?>

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

Вместо вывода: инкапсуляция, модификаторы доступа и наследование уже сильно отличается от использования простых функций. Расширение возможностей классов намного лучше переписывания отдельных функций или методов суперклассов. Поэтому использовать их хорошо.

Вместо заключения. Я, конечно, не ожидал такого отклика на первую статью. Тем более удивительно, что рейтинг на аккаунте стал немного больше, а не наоборот. Значит, все не зря. Более того, 63 человека стали подписчиками. Это уже совсем удивительно, ведь судя по комментариям, про ооп все уже все знают. Наверное, вы подписались из-за искрометных мемчиков вначале постов. В общем, всем спасибо! И отдельное спасибо новым подписчикам на ютубе :)

Что рассмотрим в следующий раз?
Всего голосов:
Показать полностью 1

Ответ на пост «Поговорим про ооп»

Эх... Проще всего ООП несведущему человеку объяснять на примере бригады строителей. Например вы офигенный строитель и делаете всё сами - сами льёте бетон, сами штукатурите, сами красите. С такого подхода начиналось программирование - всё делает один человек отдавая все свои доступные ресурсы, только в случае с программированием всем занимался один человек. Это были времена одноядерных процессоров с одним потоком выполнения. Человеку (потоку выполнения) было не очень хорошо работать - всегда всё нужно держать в голове и крайне желательно всё делать в строгой последовательности, чтобы не поклеить обои на неоштукатуренную стену. Потом люди придумали процедуры и функции - началось разделение на специальности. Прораб знает, что надо стены сначала возвести, потом оштукатурить, потом окрасить или поклеить обои и запускает соответствующие процедуры или функции в соответствующем порядке - уже лучше, но такой подход всё же имеет определенные минусы - прораб всё ещё контролирует всё сам. Затем началась эра многопроцессорности, многопоточности и многозадачности. Прораб нанял бригаду. В бригаде каменщик-бетонщик, штукатур и маляр. Принципы работы каждой специальности известны. В простом варианте тот кто клеит обои должен нанести на обои и стену клей, прилепить полосу обоев на стену. Повторять так пока вся стена не будет оклеена обоями, а потом отчитаться прорабу (главному потоку выполнения). Это всё ещё функция.

Чем класс в данном контексте отличается от функции? У класса есть свойства и методы. Это такой свод правил для каждой специальности - для бетонщиков, для штукатуров, для маляров - для каждой специальности отдельно. Когда вы нанимаете пять маляров, вы создаёте пять экземпляров класса маляр. У класса есть свойства. Это например возраст маляра, его рост (мелким малярам сложнее работать без стремянки), вес (некоторым малярам возможно понадобится более основательная стремянка), имя и например оклад. Набирая пяток маляров свойства у каждого из них будут отличаться и как говорит известная телеведущая - это нормально. А вот методы работы у них должны быть строго одинаковые!

Теперь к наследованию. Если мы пойдём в истории нашей бригады чуть назад, то мы поймём что все они строители (базовый класс - строитель), все они имеют некий общий набор свойств перечисленных выше. А вот уже от строителей отходят классы наследники - штукатуры, маляры и бетонщики. При этом каждый базовый "строитель" умеет таскать песок - то есть наши специализированные классы унаследовали от родительского такую возможность и в ООП это называется наследованием. Но иногда вы нанимаете шикарного маляра, который говорит: "я кароч песок таскать не буду, но зато смотри как шикарно я крашу!" И тогда это уже другой класс маляра - маляр-профессионал. Ему негоже таскать песок, но красит на пятёрочку и по другим методикам - это называется полиморфизм. На попытку заставить его таскать песок он ответит отказом, а покрасит лучше простого маляра. Это потомучто он переопределил в себе методы родителя CarryingSand() и PaintingAWalls(). Теперь к инкапсуляции. Если методичка по покраске стен написана хорошо, верно и конкретный Махмуд не несёт отсебятины, то результат предсказуем и повторяем. И самое главное нет нужды стоять у него над душой и контролировать процесс. В жизни так конечно не бывает, но мы предположим, что такие чудесные люди существуют в этом мире. Вот в таком случае считается что метод инкапсулирован и не важно что делает ваш маляр - важен итоговый результат или мотивированный отказ с указанием причины почему это сделать невозможно (например нет сен под покраску). Это конечно сильно утрированный пример, но зато понятнее для обывателя.

Показать полностью

Простые требования легче реализовывать

Всем привет, работаю java разработчиком 10 лет. Хотел бы на примере пояснить, почему важно внимательно вникать в требования, и не допускать их избыточного утяжеления.

Представим, что нам нужно сделать систему, проводящую платежные поручения, и у каждого поручения должен быть свой уникальный идентификатор. Поддержку уникальности осуществляет реляционная база данных, идентификатор используется как primary key. Какой тип и правило задать для генерации идентификатора?

  • integer, числовая последовательность: 0001, 0002, ...

  • UUID.random() : 8c061868-5bbd-4ea7-824f-d8640fb4f6e3, ...

UUID может совпасть при двух генерациях, но с крайне малой вероятностью - можно сказать что он уникален. Значения в последовательности тоже уникальны. То есть уникальность поддерживается там и там.

Так как эти уникальные значения можно сравнивать, то можно привести их к полному порядку - отсортировать и расположить в виде структуры с эффективным доступом (например, дерево со сложностью logN).

Числовая последовательность обеспечивает не какой-то порядок - он еще и совпадает с порядком добавления записей в таблицу. Если в конце месяца мы захотим подарить подарок 1000-му пользователю сервиса, то это можно сделать если исходный порядок сохранен.

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

main: (0001, 0002, 0003)
replica: (0001, 0002)

Если основной узел выйдет из строя, то дальше все операции по записям возьмет на себя реплика. В указанном случае она будет выдавать идентификаторы далее: 0003, 0004, ... . Получается, у разных узлов будет разное представление об операции с id = 0003 - это создаст конфликт, если первый узел вернется к жизни.

Можно было бы вместо этого выбирать тысячную запись не по id, а по времени создания. В этом случае можно использовать UUID как идентификатор, и добавлять время создания записи, чтобы позже по нему выявить 1000-го пользователя. В случае падения основного узла конфликта с id не будет, но на разных узлах может не совпадать время - а это бывает при проблемах с ntp сервисами. Например, во время выхода из строя основного узла время на нем было 15:20, а на реплике 15:12, и у новых пользователей время будет меньше чем у существующих.

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

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

Показать полностью

Поговорим про ооп

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


Поговорим про ооп PHP, Программирование, Ооп, Oop, Длиннопост

Мем из интернетов

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

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

Еще позднее функций стало недостаточно и программисты придумали классы и объекты.
Класс - часть программы, которая может содержать внутри функции и переменные, оформленная для многократного использования в более сложных конструкциях.
Предположим, мы хотим создать программу, которая выведет строку "Hello, world!" несколько раз.
На PHP это будет выглядеть, например так:

Здесь три команды вывода текста на экран. Поэтому удобно использовать функцию:

<?php
echo 'Hello, world!';
echo 'Hello, world!';
echo 'Hello, world!';
?>

Если вдруг, мы захотим внести изменения в программу и выводить другой текст, или, например, добавить перевод строки после текста, нам придется изменить только одну функцию в одном месте. А вызов функции останется неизменным.

<?php
function hello(){
echo 'Hello, world!';
}
hello();
hello();
hello();
?>

Что на счет ООП?

Создадим класс Текст. Он будет печатать текст и хранить этот текст внутри себя.

<?php
class Text{
public $text = 'Hello, world!';
function printText()
{
echo $this->text;
}
}
$hello = new Text();
$hello->printText();
?>

Здесь у нас класс Текст. У него есть общедоступное свойство текст, которое равно "Hello, world" и метод, который выводит этот текст на экран. Из такого простого примера не очень понятна выгода классов по отношению к простым функциям. Однако такой класс имеет рад преимуществ.

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

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

В-третьих, наследование, полиморфизм и паттерны программирования. Здесь скрыта магия ооп. Но раскрыть ее в одной статье будет, пожалуй, невозможно.

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

В будущих статьях я попробую описать все основные моменты работы с ооп. Попробую разобраться в ни сам и объяснить заинтересованным. Так что, присоединяйтесь.

В заключении. Если мои странные объяснения показались или могут показаться вам полезными, присоединяйтесь на пикабу и на ютуб. Ссылка в профиле. Осторожно, видео на непонятном языке.

Показать полностью 1

Курс Python-программист 04. Логические операторы

Всем привет! На этой неделе планирую запустить первый стрим, отвечу на вопросы и выслушаю пожелания :)
Все анонсы и новости в ТГ https://t.me/davaite_pro_it

Интерфейсы и абстрактные классы

Случилась со мной такая история ...

Недавно проходил собеседование на Java разработчика, как и на всех собеседованиях, задали вопрос про интерфейсы и абстрактные классы. Конечно, ответил, но все же решил перепроверить информацию на эту тему, так что здесь будет вся моя выдержка за это время

Давайте начнем с базовых ответов по теме интерфейс и абстрактный класс.

На вопрос: "Причем тут абстрактный класс?", отвечу так: "На собеседованиях эти вопросы идут рядом и в целом чем-то они похожи".

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

В те времена можно было наследовать много абстрактных классов и Василий не был исключением, наследовали его и всех его родственников. Но так получилось, что множественное наследование приводило к ошибкам наследования (одинаковые методы классов постоянно сорились) тогдв многие абстрактные классы иммигрировали в другие страны, а вместо них к Василию иммигрировали интерфейсы из public abstract Ифрики (нельзя наследовать много классов, но можно реализовывать много интерфейсов)

Таким образом Василий познакомился с интерфесом Амбалой. Амбала рассказал Василию, что он не содержит конструктора и реализовать его нельзя соответственно Методы интерфейса public и abstract по умолчанию

interface SomeInterface {

int SOME_THING = 11;

int foo();

}

Еще Амбала рассказал Василию, что содержит поле, но его поля только публичные, константные и статические, тогда как у Василия поля могут быть какими угодно. Но так было у предков Амбалы, тогда сам Амбала может содержать методы по умолчанию - медоты имеющие реализацию

interface SomeInterface {

default int foo() {

System.out.println("foo");

}

}

Также Амбала может иметь и статические методы, а обращаться к ним можно также как и к статическим методам класс

interface SomeInterface {

static int foo() {

System.out.println("foo");

}

}

public static void main(String[] args) {

SomeInterface.foo();

}

Шли годы и у Амбалы появились дети (jdk 9), они уже умели делать свои методы приватными и эти приватные методы могут быть как статическими так и нет.

Также к Амбале приехали родственники из Ифрики, оказалось, что они не содержат ни методов ни полей. "Как так получилось" - спросил Василий: "Что они умеют делать???".

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

interface Printable { }

class SomeClass implements Printable {

private int magicNumber = 3;

public int getMagicNumber() {

return magicNumber;

}

@override

public String toString() {

return String.valueOf(magicNumber);

}

}

public class Main {

public static void main(String[] args) {

var someClass = new SomeClass();

print(someClass);

}

public static void print(Printable printable) {

System.out.println(printable);

}

}

Суть в том, что тема интерфейсов оказалось гораздо интереснее чем я думал.

P.S помимо прочего веду телеграмм-канал и буду рад если поддержите IT-литературу.

Показать полностью

Подскажите книгу по управлению в тестировании

Посоветуйте книгу по управлению людьми/проектами, людьми и проектами в тестировании или просто достойную книгу про управлении в этой сфере и сфере разработки ПО.
Книга нужна для уже опытного руководителя отделом тестирования.

Войти в IT

Приветствую всех. Подскажите пожалуйста. Натолкнуло меня на этот вопрос волна приложений "честная цена".

Допустим, новичок хочет быть программистом - делать небольшие игры. Но при этом понимает, что игродел - это скорее хобби, а хотелось бы в дальнейшем какую-никакую, а копейку за свою работу получать, а кому этого бы не хотелось?


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

Но, начиная изучать что-то из этого, понимаешь - что-то тут не то.
Из популярных языков - это либо, огромный локомотив типа С# и .NET, на котором можно сделать абсолютно ВСЁ, но в то же время и ничего, потому как реализация через фреймворки определенных задач будет похожа на забивание гвоздя отверткой.

Либо это легкий и непринужденный инструмент, вроде Python, на котором можно сделать тоже абсолютно ВСЁ, но это всё будет несерьезным и легковесным, скорее как дополнение к чему-то.

Либо это совсем какие-то узконаправленные языки, на которых кроме определенной задачи ничего и не сделаешь. Вот создан язык, чтобы на нем сайты делать - вот и делай на нём только сайты.


Казалось бы, всё просто, так оно и работает, в одиночку никто проекты не разрабатывает и в проектах как раз и есть условные 3 человека, которые знают все эти 3 разные технологии и объединяют в единое целое. НО!

НО! Тогда кто все эти люди, которые за вечер клепают свои альфа проекты? Они тебе и игры запилят, и сайты, и десктоп, и андроид приложения. И вообще оказывается это всё они пилят после просмотра пары роликов на ютуб. Но не могут же они знать абсолютно все технологии и языки, чтобы так легко переключаться с одного на другой?

И так с абсолютно каждым языком. У кого ни спроси - это всегда какие-то абстрактные ответы по типу, что для каждой задачи свой язык.
Неужели среди программистов, где чуть ли не правило - не изобретать велосипед, если его уже сделали до тебя, до сих пор нет понятного примерного плана пути для начинающего? Не того road map, где стрелочками отмечены абсолютно все существующие технологии по определенной сфере, а что-то понятное, то через что проходили все, прежде чем стать профессионалами, прежде чем начать делать что-то своё?

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

P. S. Я знаю, что сейчас в IT не войти, надо работать на заводе, а на 100 резюме джунов приходится всего 1 вакансия. У меня другая работа, которая устраивает. Это скорее попытка узнать, какую ошибку я совершил в молодые годы, когда выпустился из техникума со специальностью "информационные технологии", где максимум тебя научили писать "hello, world" на двух разных ЯП, а из-за обилия выбора направлений в дальнейшем я запутался, заблудился и не воспользовался шансом, когда он еще был.

Показать полностью
Отличная работа, все прочитано!