Найти - Пользователи
Полная версия: ООП - проектирование классов и их взаимодействия.
Начало » Python для экспертов » ООП - проектирование классов и их взаимодействия.
1
Nab
Решил попробовать ооп на практике. Хочу знать насколько правильно получилось спроектировать сами классы. Так же хотелось бы увидеть ошибки взаимодействия между классами. Насколько правильно всё получилось.
# coding=utf-8
from random import randrange
import random
from abc import abstractmethod
class ВзрывоопаснаяЧасть:
    __врывная_сила = None
    def __init__(сам, взрывная_сила=10):
        сам.задаёт_взрывную_силу(взрывная_сила)
    def взрывается(сам, целевой_объект = None):
        print("Происходит Взрыв!")
        if not целевой_объект:
            попавшие_под_взрыв = сам.__находит_кого_зацепило_взрывной_волной()
            if попавшие_под_взрыв:
                print("попавшие под взрыв теряют здоровье")
                сам.__попавшие_под_взрыв_теряют_здоровье(попавшие_под_взрыв)
            else:
                print("Взрывом никого не зацепило.")
        else:
            целевой_объект.получает_повреждения(сам.выдаёт_взрывную_силу())
            return сам.выдаёт_взрывную_силу()
    def задаёт_взрывную_силу(сам, взрывная_сила):
        сам.__врывная_сила = взрывная_сила
    def выдаёт_взрывную_силу(сам):
        return сам.__врывная_сила
    def __находит_кого_зацепило_взрывной_волной(сам):
        """
        Это такая длинная заглушка.
        Так как расстояний нет, то просто выбирается список случайных кораблей,
        из обоих флотов.
        Эта заглушка, позволяет программе-таки работать.
        """
        кол_накрытых_кораблей = random.randrange(
            (флот_игрока.показывает_свой_размер() +
             флот_инопланетян.показывает_свой_размер()) // 2)
        список_всех_кораблей = флот_игрока._АбстрактныйФлот__состав + \
                               флот_инопланетян._АбстрактныйФлот__состав
        список = []
        for _ in range(кол_накрытых_кораблей):
            список.append(список_всех_кораблей.pop(
                random.randrange(len(список_всех_кораблей))))
        return список
    def __попавшие_под_взрыв_теряют_здоровье(сам, попавшие_под_взрыв):
        print("Эти корабли попали под взрыв: ", end=" ")
        for корабль in попавшие_под_взрыв:
            print(корабль.выдаёт_имя(), end=", ")
        print(".")
        for объект in попавшие_под_взрыв:
            объект.получает_повреждения(сам.выдаёт_взрывную_силу())
class Двигатель:
    __мощность = None
    def __init__(сам, мощность):
        сам.задаёт_мощность(мощность)
        сам.энергоблок = ВзрывоопаснаяЧасть(100)
    def задаёт_мощность(сам, мощность):
        сам.__мощность = мощность
    def выдаёт_мощность(сам):
        return сам.__мощность
    def разрушается(сам):
        print("Энергоблок двигателя разрушен.")
        сам.энергоблок.взрывается()
class АбстрактныйКосмическийОбъект:
    __прочность = None
    __скорость = None
    def __init__(сам, прочность):
        сам.задаёт_прочность(прочность)
        сам.задаёт_скорость(0)
    def задаёт_прочность(сам, прочность):
        сам.__прочность = прочность
    def выдаёт_прочность(сам):
        return сам.__прочность
    def задаёт_скорость(сам, скорость):
        сам.__скорость = скорость
    def выдаёт_скорость(сам):
        return сам.__скорость
    @abstractmethod
    def получает_повреждения(сам, значение):
        pass
    def __остался_ли_запас_прочности(сам):
        if сам.выдаёт_прочность() > 0:
            return True
        else:
            return False
class Снаряд(АбстрактныйКосмическийОбъект):
    def __init__(сам, прочность, взрывная_сила=10):
        АбстрактныйКосмическийОбъект.__init__(сам, прочность)
        сам.боеголовка = ВзрывоопаснаяЧасть(взрывная_сила)
    def летит_в_цель(сам, цель):
        сам.__следует_правилам_баллистики()
        print("снаряд полетел ", end="")
        попадание = сам.__попал_ли_в_цель()
        if попадание:
            print("и попал в", цель.выдаёт_имя())
            сам.__сталкивается_с(цель)
        else:
            print("в бесконечный космос.")
    def __сталкивается_с(сам, цель):
        сам.получает_повреждения(сам.выдаёт_прочность())
        # отправляет сообщение объекту "корабль"... или любой другой цели
        цель.получает_повреждения(сам.боеголовка.взрывается(цель))
    def __следует_правилам_баллистики(сам):
        pass
    def __попал_ли_в_цель(сам):
        return random.choice([True, False])
    def получает_повреждения(сам, значение):
        сам.задаёт_прочность(значение)  # прочность снижается до нуля
        print("Снаряд разрушается.")
class КосмическийКорабль(АбстрактныйКосмическийОбъект):
    """Более крупный пример агрегации."""
    __имя = None
    def __init__(сам, *, прочность, имя):
        АбстрактныйКосмическийОбъект.__init__(сам, прочность)
        сам.двигатель = Двигатель(100)
        сам.задаёт_прочность(прочность)
        сам.задаёт_имя(имя)
    def выдаёт_имя(сам):
        return сам.__имя
    def задаёт_имя(сам, прочность):
        сам.__имя = прочность
    def полный_вперёд(сам):
        сам.задаёт_скорость(сам.двигатель.выдаёт_мощность())
        print(сам.выдаёт_имя(), "набрал максимальную скорость")
    def стреляет(сам, цель):
        print("Корабль :", сам.выдаёт_имя(), "атаковал и его ", end="")
        снаряд = Снаряд(10)
        снаряд.летит_в_цель(цель)
    def __выбирает_цель(сам):
        цель = сам.цель = "цель"
        return цель
    def получает_повреждения(сам, значение):
        """Грёбаная рекурсия"""
        print("Корабль", сам.выдаёт_имя(), "получил", значение, "урона.")
        сам.задаёт_прочность(сам.выдаёт_прочность() - значение)
        if сам.__был_ли_уничтожен():
            if "двигатель" in сам.__dict__:  # проверяет, наличие двигателя
                сам.двигатель.разрушается()
                if "двигатель" in сам.__dict__:
                    del сам.двигатель
            сам.уничтожается()
        else:
            if "двигатель" in сам.__dict__:
                if сам.__был_ли_повреждён_двигатель():
                    сам.двигатель.разрушается()
                    if "двигатель" in сам.__dict__:
                        del сам.двигатель
    def __был_ли_повреждён_двигатель(сам):
        # заглушка, с определённой вероятностью повреждается двигатель.
        процент = random.randint(0, 100)
        if процент <= 20:
            return True
        else:
            return False
    def __был_ли_уничтожен(сам):
        if сам.выдаёт_прочность() <= 0:
            return True
    def уничтожается(сам):
        pass
class АбстрактныйФлот:
    """Флот для наследования."""
    __состав = None  # список
    def __init__(сам, количество_кораблей, имя="Линкор"):
        сам.__состав = []
        сам.__пополняет_свой_состав(количество_кораблей, имя)
    def добавляет_в_свой_состав(сам, корабль):
        if сам.__является_ли_объект_кораблём(корабль):
            сам.__состав.append(корабль)
    def удаляет_из_своего_состава(сам, корабль):
        if сам.__является_ли_объект_кораблём(корабль):
            сам.__состав.remove(корабль)
    def показывает_свой_состав(сам):
        for корабль in сам.__состав:
            print("Название: ", корабль.выдаёт_имя(), "|",
                  "прочность:", корабль.выдаёт_прочность())
    def выбирает_один_из_своих_кораблей(сам, порядковый_номер=None):
        if not порядковый_номер:
            корабль = сам.__выбирает_свой_случайный_корабль()
        else:
            корабль = сам.__ищет_корабль_по_порядковому_номеру(порядковый_номер)
        return корабль
    def показывает_свой_размер(сам):
        return len(сам.__состав)
    @abstractmethod
    def атакует(сам, флот_противника):
        """Метод должен переопределяться в обязательном порядке."""
        pass
    def __пополняет_свой_состав(сам, количество_кораблей, имя):
        порядковый_номер = 0
        for _ in range(количество_кораблей):
            порядковый_номер += 1
            корабль = КосмическийКорабль(прочность=100,
                                         имя=имя + str(порядковый_номер))
            сам.добавляет_в_свой_состав(корабль)
    def __выбирает_свой_случайный_корабль(сам):
        корабль = сам.__ищет_корабль_по_порядковому_номеру(
            random.randrange(сам.показывает_свой_размер()))
        return корабль
    def __ищет_корабль_по_порядковому_номеру(сам, порядковый_номер):
        корабль = сам.__состав[порядковый_номер]
        return корабль
    @staticmethod
    def __является_ли_объект_кораблём(корабль):
        return корабль.__class__ is КосмическийКорабль
class ФлотИгрока(АбстрактныйФлот):
    """Конкретизация флота. Ассоциация."""
    def атакует(сам, флот_противника):
        """Пример полиморфизма."""
        print("Флот игрока атакует!")
        номер_корабля = сам.__спрашивает_у_игрока_номер_корабля()
        корабль = сам.выбирает_один_из_своих_кораблей(номер_корабля)
        корабль_цель = флот_противника.выбирает_один_из_своих_кораблей()
        корабль.стреляет(корабль_цель)
    @staticmethod
    def __спрашивает_у_игрока_номер_корабля():
        # Игрок выбирает корабль
        return 1  # заглушка
class ФлотИнопланетян(АбстрактныйФлот):
    """Конкретизация Флота. Ассоциация."""
    def __init__(сам, кол_кораблей):
        АбстрактныйФлот.__init__(сам, кол_кораблей, "НЛО")
    def атакует(сам, флот_противника):
        """Пример полиморфизма."""
        print("Флот инопланетян атакует!")
        сам.__случайно_выбранный_корабль_стреляет(флот_противника)
    def __случайно_выбранный_корабль_стреляет(сам, флот_противника):
        корабль = сам.выбирает_один_из_своих_кораблей()
        корабль.стреляет(флот_противника.выбирает_один_из_своих_кораблей())
флот_игрока = ФлотИгрока(5)
print("Флот собран.")
print("Состав флота игрока :")
флот_игрока.показывает_свой_состав()
print("\n\n")
флот_инопланетян = ФлотИнопланетян(5)
print("Флот собран.")
print("Состав флота инопланетян :")
флот_инопланетян.показывает_свой_состав()
print("\n\n")
флот_игрока.атакует(флот_инопланетян)
флот_инопланетян.атакует(флот_игрока)
print("Состав флота игрока :")
флот_игрока.показывает_свой_состав()
print("Состав флота инопланетян :")
флот_инопланетян.показывает_свой_состав()
print("\n\n")

Так как система сложная, всё-таки, то вот диаграмма в помощь.


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

пс: про @property вкурсе, без него решил делать намеренно.

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

Вобщем, очень хотелось бы услышать мнение человека, имеющего хороший практический опыт в ооп.
FishHook
Вы, надеюсь, не собираетесь дальше в кириллице работать?
Не мучайте наши глаза не надо вот этого извращения сам.__состав, пишите сразу код.
JOHN_16
Nab
представьте себе светлое будущее и кому то понравилась ваша игра и он захотел присоединиться к разработке, а он из Европы/Индии/Америк…. а нет он больше не хочет присоединиться к разработке..тут не код, а какие то каракули. Он ничего прочесть не может.
Это конечно очень условный пример, но все же подчеркивает одно важное обстоятельство - международный язык программистов - английский. И да да, это проект домашний и только для вас и т.д. и т.п., но привыкайте сразу делать правильно.
doza_and
посмотрю когда переведете на английский, причем нормально а не транслитерацией.
Nab
У вас тут секта что-ли?
Все как один ответили обращаясь на вы, при этом проявляя невежливость и бестактность.
Ну не хотите не помогайте, зачем писать сюда было. Если помочь некому, тема сама утонет.

ПС: не вижу смысла для русских людей, переводить с русского на английский, чтобы им легче читалось - даже звучит дико. Хотя может “вы” нерусские
FishHook
Nab
Не вижу смысла тебе дальше быть на форуме. Прощай.
Закройте тему, кто может.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB