Точка входа в программирование
21.4K subscribers
913 photos
164 videos
1 file
2.46K links
Фундаментальные знания по основам программирования

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/zrgj
Download Telegram
ООП простым языком

Большое видео по объектно-ориентированному программированию, в котором на примере кода на TypeScript разобраны базовые понятия и принципы ООП:

https://youtu.be/-6DWwR_R4Xk

Что интересно, автор простым языком объяснил темы, на которые редко обращают внимание новички — внедрение зависимостей и паттерн singleton.

#ооп
Вложенные классы в Java

В Java можно реализовать класс внутри другого класса, и его называют вложенным. Обычно это требуется, когда классы логически связаны друг с другом.

Существует 4 типа вложенных классов:
1. Статические классы привязаны к классу, а не объекту.
2. Нестатические или внутренние классы привязаны к конкретному экземпляру, а не к классу.
3. Локальные классы похожи на внутренние, но могут быть определены в любом блоке кода.
4. Анонимные классы не имеют имени и создаются уже внутри экземпляра.

Подробнее о вложенных классах: https://tprg.ru/JyXC

#java #ооп
Зачем нужны интерфейсы в Java?

Как создать интерфейс в коде, понять несложно. Но когда их применять на практике, если классы могут сами наследовать другие классы? Разберёмся на простом практическом примере:

https://tprg.ru/6OCH

#java #ооп
Вы неправильно учили объектно-ориентированное программирование

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

Статья поможет выстроить более чёткое понимание ООП как парадигмы:

https://tprg.ru/eqA3

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

После изучения базового синтаксиса Python стоит перейти к парадигме ООП и использованию её на практике — работа с классами и объектами.

В Python встроено множество полезных конструкций для работы с классами. Освоить их можно по серии уроков на YouTube, где подробно рассказано про:
— классы и объекты;
— наследование, полиморфизм и инкапсуляцию;
— магические методы;
— обработку исключений.

Плейлист на YouTube: https://tprg.ru/An0r

#python #ооп
Топ вопросов по ООП с собеседований

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

В подборке собраны наиболее популярные вопросы, которые помогут подготовиться к собеседованию.

Первая часть: https://tprg.ru/fJ0w

Вторая часть: https://tprg.ru/kYFz

#ооп #собеседование
Готовимся к собеседованию: вопросы по ООП

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

https://tprg.ru/v9Rf

#ооп #собеседование
​​Почему в ООП приватные свойства лучше публичных?

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

Автор видео разобрал на конкретных примерах кода, почему приватные свойства необходимо использовать и чем чревата их замена на публичные:

https://youtu.be/0lQFrD7kq3k

#ооп
Принципы SOLID простым языком

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

Стоит ли соблюдать принципы SOLID или нет в проекте?
В этой статье рассматриваются подробно все правила и примеры, на которых явно видно, что происходит с архитектурой проекта, если не следовать этим принципам:

https://habr.com/ru/company/itentika/blog/694730/

#ооп
ООП за 10 минут

В этом коротком видео рассказывается об основах объектно-ориентированного программирования (ООП).

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

#видео #ооп
Инкапсуляция в ООП

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

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

#начинающим #ооп
Простыми словами: Основные концепции ООП

Понять объектно-ориентированное программирование на старте изучения может быть сложно. Поэтому мы постараемся объяснить вам основные концепции максимально простым языком.

Для начала разберёмся с тем, что же такое объекты, а затем пройдёмся по основным концепциям — наследованию, абстракции, инкапсуляции и полиморфизму:

Классы и объекты

Класс — это своего рода чертёж или шаблон, по которому создаются объекты. Это как кулинарный рецепт, который описывает, какие ингредиенты (свойства) и шаги (методы) нужно использовать.

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

class Кот:
def __init__(self, имя):
self.имя = имя

def мяукать(self):
print(f"{self.имя} говорит: Мяу!")

мой_кот = Кот("Мурзик")
мой_кот.мяукать()


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

Наследование позволяет создавать новый класс на основе существующего. Это как брать основу от одного рецепта и добавлять свои изменения.

class Животное:
def дышать(self):
print("Дышу")

class Кот(Животное):
def мяукать(self):
print("Мяу!")

кот = Кот()
кот.дышать()
кот.мяукать()


2. Абстракция

Абстракция — это концепция, позволяющая скрыть сложность системы, выделяя только ключевые аспекты и упрощая взаимодействие с объектами. Это как пользоваться телевизором: вы знаете, какие кнопки нажимать, но не обязаны понимать, как работает вся электроника внутри.

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

Инкапсуляция — скрытие внутренней реализации объекта от внешнего мира и предоставление доступа только через определённые методы. Это как секретный ингредиент у шеф-повара, который скрыт от всех, кроме него.

class Кот:
def __init__(self, имя):
self.__имя = имя # сокрыто (private)

def получить_имя(self):
return self.__имя

def мяукать(self):
print(f"{self.__имя} говорит: Мяу!")

кот = Кот("Мурзик")
print(кот.получить_имя())
кот.мяукать()


4. Полиморфизм

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

class Животное:
def издать_звук(self):
pass

class Кот(Животное):
def издать_звук(self):
print("Мяу!")

class Собака(Животное):
def издать_звук(self):
print("Гав!")

животные = [Кот(), Собака()]

for животное in животные:
животное.издать_звук()


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

Если вам понравился пост, поставьте ❤️ и мы обязательно расскажем о чём-то ещё.

#простымисловами #ооп
Простыми словами: Наследование в ООП

В прошлом посте мы рассказали про основные концепции ООП в общих чертах. Теперь давайте поговорим о них более конкретно и разберём первую — наследование.


Что такое наследование?

Наследование — это механизм, позволяющий одному классу наследовать свойства и методы другого класса. Это позволяет создавать новый функционал на базе существующего. У этого принципа есть два основных достоинства:

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

Давайте рассмотрим простой пример с животными, где общие свойства и методы будут находиться в родительском классе.

# Родительский (суперкласс)
class Животное:
def __init__(self, имя, возраст):
self.имя = имя
self.возраст = возраст

def издать_звук(self):
raise NotImplementedError("Этот метод должен быть определён в подклассе")

def описание(self):
return f"{self.имя} — {self.возраст} лет"

# Дочерний класс Кот наследует от Животное
class Кот(Животное):
def издать_звук(self):
return "Мяу!"

# Дочерний класс Собака наследует от Животное
class Собака(Животное):
def издать_звук(self):
return "Гав!"

# Создаём объекты
кот = Кот("Мурзик", 3)
собака = Собака("Бобик", 5)

# Используем методы
print(кот.описание()) # Output: Мурзик — 3 лет
print(кот.издать_звук()) # Output: Мяу!
print(собака.описание()) # Output: Бобик — 5 лет
print(собака.издать_звук()) # Output: Гав!


Ключевые моменты в наследовании:

1. Конструктор родительского класса


Для инициализации объектов дочернего класса важно вызвать конструктор родительского класса. В Python это делается с помощью функции super().

class Животное:
def __init__(self, имя, возраст):
self.имя = имя
self.возраст = возраст

class Кот(Животное):
def __init__(self, имя, возраст, цвет):
super().__init__(имя, возраст)
self.цвет = цвет

кот = Кот("Пушок", 2, "серый")
print(кот.описание()) # Output: Пушок — 2 лет
print(кот.цвет) # Output: серый


2. Переопределение методов

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

class Животное:
def __init__(self, имя, возраст):
self.имя = имя
self.возраст = возраст

def издать_звук(self):
return "Звук животного"

class Кот(Животное):
def издать_звук(self):
return "Мяу!"

кот = Кот("Мурзик", 3)
print(кот.издать_звук()) # Output: Мяу!


3. Множественное наследование

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

class Животное:
def дышать(self):
return "Дышу"

class Летать:
def летать(self):
return "Летаю"

class Птица(Животное, Летать):
def издать_звук(self):
return "Чирик"

птица = Птица()
print(птица.дышать()) # Output: Дышу
print(птица.летать()) # Output: Летаю
print(птица.издать_звук()) # Output: Чирик


Возможно, вы сейчас задаётесь вопросом где же это применяется на практике? Например, тут:

1. Интерфейсы GUI. При разработке графических интерфейсов часто используют наследование для создания различных элементов интерфейса.

2. Системы управления пользователями. В системах управления пользователями можно использовать наследование для создания различных ролей с различными уровнями доступа.

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

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

#простымисловами #ооп
Варианты ответа ниже. Я верю, вы справитесь 💪

#викторина #ооп
Простыми словами: Что такое абстракция в ООП

Про наследование мы уже рассказали. Теперь поговорим про абстракцию.

Абстракция — это концепция, которая помогает скрыть сложные внутренние детали и выделить только ключевые аспекты объекта. Это как использование бытового прибора: вы знаете, какие кнопки нажимать, но не обязаны понимать, как он работает изнутри.

Зачем нужна абстракция?

1. Упрощение взаимодействия: Абстракция упрощает использование сложных систем, предоставляя понятные и удобные интерфейсы.
2. Сокрытие деталей реализации: Позволяет скрывать детали, которые не важны для пользователя объекта.
3. Повторное использование кода: Обеспечивает создание общих интерфейсов, которые могут быть использованы в различных контекстах.

Пример 1: Абстрактные классы

В некоторых языках программирования, таких как Python, Java или C#, существуют абстрактные классы. Они содержат методы, которые должны быть реализованы в дочерних классах.

from abc import ABC, abstractmethod

class Животное(ABC):
@abstractmethod
def издать_звук(self):
pass

class Кот(Животное):
def издать_звук(self):
print("Мяу!")

class Собака(Животное):
def издать_звук(self):
print("Гав!")

животные = [Кот(), Собака()]

for животное in животные:
животное.издать_звук()


Здесь Животное — это абстрактный класс с абстрактным методом издать_звук, который обязаны реализовать все дочерние классы, такие как Кот и Собака.

Пример 2: Интерфейсы (в других языках)

В языках программирования, таких как Java или C#, существуют интерфейсы, которые определяют набор методов, которые должны быть реализованы классами.

interface Животное {
void издатьЗвук();
}

class Кот implements Животное {
public void издатьЗвук() {
System.out.println("Мяу!");
}
}

class Собака implements Животное {
public void издатьЗвук() {
System.out.println("Гав!");
}
}

public class Main {
public static void main(String[] args) {
Животное кот = new Кот();
Животное собака = new Собака();

кот.издатьЗвук(); // Output: Мяу!
собака.издатьЗвук(); // Output: Гав!
}
}


Здесь Животное — это интерфейс, который определяется методом издатьЗвук, что должен быть реализован в классах Кот и Собака.

Давайте теперь посмотрим, где применяется эта концепция в реальной жизни:

1. Управление пользователями. Абстракция позволяет создавать общие интерфейсы для работы с пользователями различных типов — например, администраторы и обычные пользователи.

from abc import ABC, abstractmethod

class Пользователь(ABC):
@abstractmethod
def доступ(self):
pass

class Админ(Пользователь):
def доступ(self):
return "Полный доступ"

class Гость(Пользователь):
def доступ(self):
return "Доступ в режиме чтения"

пользователи = [Админ(), Гость()]
for пользователь in пользователи:
print(пользователь.доступ())


2. Работа с данными. Часто используется, когда нужно создать общий интерфейс для работы с разными источниками данных.

from abc import ABC, abstractmethod

class Репозиторий(ABC):
@abstractmethod
def получить_данные(self):
pass

class SQLРепозиторий(Репозиторий):
def получить_данные(self):
return "Данные из SQL базы данных"

class APIРепозиторий(Репозиторий):
def получить_данные(self):
return "Данные из API"

репозитории = [SQLРепозиторий(), APIРепозиторий()]
for репозиторий in репозитории:
print(репозиторий.получить_данные())


3. Системы оплаты. Можно создать абстракцию для различной обработки платежей — кредитными картами, PayPal, Bitcoin и т.д.

class Платеж(ABC):
@abstractmethod
def провести_платеж(self, сумма):
pass

class КредитнаяКарта(Платеж):
def провести_платеж(self, сумма):
print(f"Платеж проведён на сумму {сумма} с кредитной карты")

class PayPal(Платеж):
def провести_платеж(self, сумма):
print(f"Платеж проведён на сумму {сумма} через PayPal")

платежи = [КредитнаяКарта(), PayPal()]
for платеж in платежи:
платеж.провести_платеж(100)


#простымисловами #ооп
Простыми словами: Инкапсуляция в ООП

Мы с вами уже разобрали наследование и абстракцию. Пришло время третьей парадигмы. Инкапсуляция — это концепция ООП, которая скрывает внутренние детали объекта и предоставляет доступ только к нужным методам и свойствам. Это как капсула с лекарством: вы знаете, как её использовать, но не видите, что внутри.

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

Давайте рассмотрим несколько примеров:

В Python инкапсуляции часто достигают с помощью именования методов и атрибутов с одним или двумя подчёркиваниями.
class Кот:
def __init__(self, имя):
self.__имя = имя # Скрытый атрибут

def получить_имя(self):
return self.__имя # Метод для получения скрытого атрибута

def мяукать(self):
print(f"{self.__имя} говорит: Мяу!")

кот = Кот("Мурзик")
print(кот.получить_имя()) # Output: Мурзик
кот.мяукать() # Output: Мурзик говорит: Мяу!

# Попытка доступа к скрытому атрибуту напрямую
# print(кот.__имя) # Это вызовет ошибку


В этом примере атрибут __имя скрыт от внешнего доступа, и доступ к нему можно получить только через метод получить_имя.

Давайте рассмотрим пример из Java. Здесь инкапсуляция достигается с помощью модификаторов доступа (private, protected, public) и методов getter/setter.
public class Кот {
private String имя; // Скрытый атрибут

public Кот(String имя) {
this.имя = имя;
}

public String getИмя() { // Метод для получения скрытого атрибута
return имя;
}

public void мяукать() {
System.out.println(имя + " говорит: Мяу!");
}

public static void main(String[] args) {
Кот кот = new Кот("Мурзик");
System.out.println(кот.getИмя()); // Output: Мурзик
кот.мяукать(); // Output: Мурзик говорит: Мяу!

// Попытка доступа к скрытому атрибуту напрямую
// System.out.println(кот.имя); // Это вызовет ошибку
}
}


В этом примере атрибут имя объявлен как private и доступен только через метод getИмя.

Где применяется?

Инкапсуляция помогает скрыть детали внутренней структуры объекта, например, банковского счёта.
class БанкСчет:
def __init__(self, баланс=0):
self.__баланс = баланс # Скрытый атрибут

def пополнить(self, сумма):
if сумма > 0:
self.__баланс += сумма

def вывести(self, сумма):
if сумма > 0 и self.__баланс >= сумма:
self.__баланс -= сумма

def получить_баланс(self):
return self.__баланс

счет = БанкСчет()
счет.пополнить(100)
счет.вывести(30)
print(счет.получить_баланс()) # Output: 70


Также позволяет управлять доступом к критическим операциям.
class Пользователь:
def __init__(self, имя, пароль):
self.__имя = имя
self.__пароль = пароль # Скрытый атрибут

def проверить_пароль(self, ввод):
return self.__пароль == ввод

пользователь = Пользователь("Иван", "12345")
print(пользователь.проверить_пароль("12345")) # Output: True
print(пользователь.проверить_пароль("54321")) # Output: False


Теперь вы знакомы с тремя составляющими ООП. Нам осталось разобраться в полиморфизме.

Если формат заходит — поставьте ❤️, я буду знать, что пишу не зря. А замечания можете написать в комментарии👇

#простымисловами #ооп #инкапсуляция
Варианты ответа, как обычно, ниже

#викторина #ооп
Media is too big
VIEW IN TELEGRAM
Плохие практики ООП в Python, которых нужно избегать

В этом видео рассматриваются распространенные ошибках в ООП на Python, которые часто совершают разработчики. Вы узнаете:

— как сохранить ваш код чистым и удобным для сопровождения;
— почему вам следует заменять ненужные классы функциями;
— зачем использовать модули вместо классов только со статическими методами;
— и как сглаживать глубокие иерархии наследования.

#видео #ооп
Простыми словами: Полиморфизм в ООП

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

Давайте же разберём подробно концепцию полиморфизма в объектно-ориентированном программировании (ООП) с примерами кода.

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

Зачем нужен полиморфизм?

1. Унификация интерфейсов позволяет использовать один интерфейс для взаимодействия с различными типами объектов.
2. Гибкость и расширяемость упрощает добавление нового функционала, так как новые классы могут использовать существующие интерфейсы.
3. Упрощение кода позволяет писать более общий и универсальный код.

Как это выглядит в коде?

В Python полиморфизм часто достигается через методические перегрузки и наследование:
class Животное:
def издать_звук(self):
raise NotImplementedError("Этот метод должен быть реализован в подклассе")

class Кот(Животное):
def издать_звук(self):
print("Мяу!")

class Собака(Животное):
def издать_звук(self):
print("Гав!")

животные = [Кот(), Собака()]

for животное in животные:
животное.издать_звук() # Output: Мяу! Гав!


В этом примере метод издать_звук вызывается для объектов различных классов (Кот и Собака), и каждый объект реализует этот метод по-своему.

В Java полиморфизм достигается через интерфейсы и абстрактные классы:
abstract class Животное {
abstract void издатьЗвук();
}

class Кот extends Животное {
@Override
void издатьЗвук() {
System.out.println("Мяу!");
}
}

class Собака extends Животное {
@Override
void издатьЗвук() {
System.out.println("Гав!");
}
}

public class Main {
public static void main(String[] args) {
Животное[] животные = { new Кот(), new Собака() };

for (Животное животное : животные) {
животное.издатьЗвук(); // Output: Мяу! Гав!
}
}
}


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

Давайте теперь посмотрим примеры кейсов, где может быть актуален полиморфизм:

1. Фигуры

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

class Фигура:
def площадь(self):
raise NotImplementedError("Этот метод должен быть реализован в подклассе")

class Круг(Фигура):
def __init__(self, радиус):
self.радиус = радиус

def площадь(self):
return 3.14159 * self.радиус ** 2

class Прямоугольник(Фигура):
def __init__(self, ширина, высота):
self.ширина = ширина
self.высота = высота

def площадь(self):
return self.ширина * self.высота

фигуры = [Круг(5), Прямоугольник(3, 4)]

for фигура in фигуры:
print(f"Площадь: {фигура.площадь()}")


2. Платежные системы

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

class Платеж(ABC):
@abstractmethod
def провести_платеж(self, сумма):
pass

class КредитнаяКарта(Платеж):
def провести_платеж(self, сумма):
print(f"Платеж проведён на сумму {сумма} с кредитной карты")

class PayPal(Платеж):
def провести_платеж(self, сумма):
print(f"Платеж проведён на сумму {сумма} через PayPal")

платежи = [КредитнаяКарта(), PayPal()]
for платеж in платежи:
платеж.провести_платеж(100)


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

#простымисловами #ооп #полиморфизм