LINUX.ORG.RU

Поиск удобной ООП системы для perl

 ,


0

3

На CPAN есть куча модулей для ООП, но те, что я видел / использовал по разным причинам меня не устраивали. Поиск продолжается...

Собственно, что хочу: protected и т.д. (с наследованием и полиморфизмом), небольшой список зависимостей, красивый синтаксис.

Пробовал Moose - как-то инопланетно (привыкнуть не смог), Class::* тоже выглядит не самым лучшим образом. Благословлённые ссылки... ну в них нет многого из перечисленного. Есть свой модуль, но вот думаю, может он - просто ещё один велосипед? Вот как мне представляется класс.

package ClassName;

    protected a => 'a';
    public 'b';
    protected c => undef;
    private d => 0xDEAD;
    
    sub method1 : Protected
        {
            ...
        }
    
    sub method2 : Public
        {
            ...
        }
    
    sub method3 : Private
        {
            ...
        }
    
1;

Если уже есть готовая отлаженная реализация, просьба сообщить.

P.S. Тролли - проходите, комментаторы - игнорируйте троллей.

★★★★★

Эта ООП система называется Ruby. Если так любишь perl, можешь запускать руби-скрипты из него, ок.

mix_mix ★★★★★
()
Ответ на: комментарий от buddhist

Без protected и private уже есть. Обсуждать нужность / ненужность сегодня не хочется. Хочется посмотреть как это реализуют другие люди, какие есть варианты.

helios ★★★★★
() автор топика

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

Moose и прибамбасы в виде MooseX (особенно Declare) мне нравились первое время, а потом понял что слишком большую цену загнули за возможность написать class ... extends ... {}; в моем уютном языке. Простые скрипты стартовали несколько секунд и жрали слишком много памяти, а мультиметоды так и не применил за ненадобностью :) В общем это уже технофетишизм.

Обхожуть своим базовым классом, Class::Accessor::Fast, несколькими полезными самописными модулями под базовые паттерны. Ну и конечно грамотное проектирование, тесты, удобный модуль реализующий гуарды на все случаи жизни.

outtaspace ★★★
()
Ответ на: комментарий от outtaspace

Да, на самом деле, всё устраивало. А тут пару дней назад приспичило: решил приделать к функциям / свойствам атрибуты приватности. И задумался. Нет, что хотел, то я сделал, но стало интересно: как у других.

helios ★★★★★
() автор топика

Уже написали про замыкания - как в кукбуках рекомендуют. Плюс сорсфильтры и м.б. аналог прагмы «base».

outtaspace ★★★
()
Ответ на: комментарий от anonymous

Мне уже интересно, чем protected плох в OOD.

Ничем. Он просто не нужен. Лишняя сущность.

Нужны методы, о которых известно лишь в рамках реализации конкретного класса? Выносим их в SomeClassImpl и экземпляр этого класса юзаем в недрах SomeClass.

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

И что, это равноценный выбор, никакого оверхеда от использования собственного велосипеда?
Просто одно дело, когда выбираешь из нескольких почти одинаковых операторов, которых в перле навалом, тогда да, равноценный выбор, а так...

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

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

У коробке с Perl очень скромный набор средств, но в CPAN-модулях десятки (если не сотни уже) реализаций оберток - в основном сахар.

outtaspace ★★★
()
Ответ на: комментарий от yoghurt

Имеешь в виду что-то вроде

package withoutprotected;

public interface Processor {

    String process(String text);
}
package withoutprotected;

import com.sun.xml.internal.ws.util.StringUtils;

class Printer {

    private final Processor processor;

    public Printer(Processor processor) {
        this.processor = processor;
    }

    public void print(String text) {
        System.out.print( processor.process(text) );
    }
}

class LowerPrinter extends Printer {

    public LowerPrinter() {
        super(new Processor() {
            @Override
            public String process(String text) {
                return text.toLowerCase();
            }
        });
    }
}

class UpperPrinter extends Printer {

    public UpperPrinter() {
        super(new Processor() {
            @Override
            public String process(String text) {
                return text.toUpperCase();
            }
        });
    }
}

class CapitalPrinter extends Printer {

    public CapitalPrinter() {
        super(new Processor() {
            @Override
            public String process(String text) {
                return StringUtils.capitalize(text.toLowerCase());
            }
        });
    }
}

public class PrinterTest {

    public static void main(String[] args) {
        String text = "tExt";
        Printer[] printers = { new LowerPrinter(), new UpperPrinter(), new CapitalPrinter() };
        for (Printer printer : printers) {
            printer.print(text);
            System.out.println();
        }
    }
}

?

Но ведь с protected проще:

package withprotected;

import com.sun.xml.internal.ws.util.StringUtils;

abstract class Printer {

    public void print(String text) {
        System.out.print( this.process(text) );
    }

    abstract protected String process(String text);
}

class LowerPrinter extends Printer {

    protected String process(String text) {
        return text.toLowerCase();
    }
}

class UpperPrinter extends Printer {

    protected String process(String text) {
        return text.toUpperCase();
    }
}

class CapitalPrinter extends Printer {

    protected String process(String text) {
        return StringUtils.capitalize(text.toLowerCase());
    }
}

public class PrinterTest {

    public static void main(String[] args) {
        String text = "tExt";
        Printer[] printers = { new LowerPrinter(), new UpperPrinter(), new CapitalPrinter() };
        for (Printer printer : printers) {
            printer.print(text);
            System.out.println();
        }
    }
}

или не?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

В этом примере не вижу смысла process() вообще вытаскивать в protected.

Если вы просто не хотите, чтобы его никто не вызывал - напишите это в документации.

anonymous
()
Ответ на: комментарий от anonymous

Может тогда и в private нет смысла? Просто написать в документации, чтоб никто не вызывал/обращался-напрямую-к-полю. И вместо final просто описать в документации, чтобы никто не изменял/переопределял/наследовал? И abstract тогда не нужен, да и interface к черту!

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Может тогда и в private нет смысла? Просто написать в документации, чтоб никто не вызывал/обращался-напрямую-к-полю. И вместо final просто описать в документации, чтобы никто не изменял/переопределял/наследовал?

Да, именно так и придумали все эти ваши перлы.

anonymous
()
Ответ на: комментарий от korvin_

Ви таки всё гиперболизировали.

Естественно, на игрушечных примерах навроде приведенного смысл не так очевиден.

Вот тут ниже по странице можно посмотреть на описанный мною ход в действии.

yoghurt ★★★★★
()
Ответ на: комментарий от anonymous

Товарищ outtaspace выше говорит, что мультиметоды оказались ненужны ему на практике.

Virtuos86 ★★★★★
()
Ответ на: комментарий от helios

Наследование обеспечивается use base, а полиморфизм тем, что $self может принадлежать дочернему пакету.

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

level1 ★★
()
Ответ на: комментарий от level1

use base

У себя сделал load + push @ISA уже давно. Про полиморфизм и наследование заговорил в связи с приватностью свойств / методов - там напоролся на проблемы.

А что с наследованием полей?

// Договариваться - это, конечно, хорошо. Но, когда по рукам бьют, например, confess'ом - действеннее.

helios ★★★★★
() автор топика
Ответ на: комментарий от helios

Если недостаточно наследования конструктора и если поля хранятся в хеше а этот хеш отдается специальным методом, то придется наследовать поля явно.

level1 ★★
()
Ответ на: комментарий от skam

Чем тебе, твой Pony::Object не угодил?)

Да всем УЖЕ угодил :). Просто я искал аналоги - может не пришлось бы его писать (дописывать, поддерживать). А раз не нашёл - допилил. Кстати, он теперь есть на CPAN http://search.cpan.org/~bugov/Pony-Object-0.03/lib/Pony/Object.pm

helios ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

Ну, _ и __ - это один вариант, для любителей подобного (перед их добавлением я поспрашивал, как людям нравится определять поля). Другой вариант - писать не has, а protected, private...

Что за змея? Нашёл snake, но он что-то выпилен со cpan'а.

И да, я открыт для предложений.

helios ★★★★★
() автор топика
Ответ на: комментарий от helios

Что за змея?

Snake case... Что-то меня не туда понесло :)

helios ★★★★★
() автор топика
Ответ на: комментарий от helios

Что за змея? Нашёл snake, но он что-то выпилен со cpan'а

Ну, очень похоже на базис объектной системы Python.

init -> __init__

Префиксы _ и __ для имитации приватной и защищенной модели доступа.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Префиксы _ и __ для имитации приватной и защищенной модели доступа.

Да, среди опрошенных были питонисты :) Но тут не имитация, тут реально будут ругаться за неправильное обращение к ним.

Вообще, да похоже, если писать на has. TMTOWTDI ;-)

helios ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.