Java добавить метод в класс - PullRequest
0 голосов
/ 03 сентября 2018

Доброе утро, у меня есть собственный класс cBigDecimal, который расширяет класс BigDecimal. Моя цель - использовать оба метода из класса BigDecimal и cBigDecimal (например, «добавить» или «умножить», а также пользовательскую функцию «процент»). Проблема в том, что «добавить» и со. вернуть BigDecimal, и, очевидно, я не могу привести его к cBigDecimal ... Есть идеи? Заранее спасибо, Lorenzo

Ответы [ 3 ]

0 голосов
/ 03 сентября 2018

Что именно делает ваш cBigDecimal класс, что не делает BigDecimal?

Это упущение дизайна, которое BigDecimal может быть расширено вообще. Джош Блох говорит в Effective Java 3-е издание, пункт 17: «Минимизируйте изменчивость»:

Широко не понималось, что неизменяемые классы должны были быть действительно окончательными при написании BigInteger и BigDecimal, поэтому все их методы могут быть переопределены. К сожалению, это невозможно исправить после факта, сохранив обратную совместимость.

Если все, что вы хотите сделать, это «добавить метод» в BigDecimal, вы можете просто создать вспомогательный метод:

static BigDecimal percent(BigDecimal b) {
  return b.divide(100);  // Or whatever it does.
}

Тогда вы можете просто иметь дело с простыми старыми BigDecimal с повсюду.

0 голосов
/ 03 сентября 2018

Я бы использовал шаблон декоратора .

По сути, вам нужно будет хранить экземпляр BigDecimal в вашем классе CBigDecimal в качестве частного члена. Для создания CBigDecimal вам понадобится экземпляр BigDecimal (который также может быть BigDecimal.ZERO).

Затем в вашем CBigDecimal классе вы можете предоставить тот же интерфейс BigDecimal (вы можете добавить метод CBigDecimal#add(BigDecimal)), потому что у вас есть экземпляр этого класса в вашем классе, и вы также можете создавать ваши собственные методы (как ваш CBigDecimal#percentage(double)).

Это пример кода:

CBigDecimal.java:

public class CBigDecimal
{
    private BigDecimal bigDecimal;

    public CBigDecimal(BigDecimal bigDecimal)
    {
        this.bigDecimal = bigDecimal;
    }

    // This method already exists in BigDecimal class, so it will have the same signature
    public CBigDecimal add(BigDecimal toAdd)
    {
        return new CBigDecimal(bigDecimal.add(toAdd));
    }

    // This is the new method which you will implement as you like
    public CBigDecimal percentage(double percentage)
    {
        BigDecimal multiplied = bigDecimal.multiply(new BigDecimal(percentage));
        BigDecimal total = multiplied.divide(new BigDecimal(100));

        return new CBigDecimal(total);
    }

    // This is another method that already exists in BigDecimal class
    public double doubleValue()
    {
        return bigDecimal.doubleValue();
    }
}

Затем клиентский код создаст экземпляр вашего CBigDecimal, предоставив его конструктору BigDecimal экземпляр.

public class CBigDecimalTest
{
     public static void main(String []args)
     {
        CBigDecimal extendedBigDecimal = new CBigDecimal(new BigDecimal(50));

        System.out.println("percentage: " + extendedBigDecimal.percentage(50).doubleValue());
        System.out.println("doubleValue: " + extendedBigDecimal.doubleValue());
     }
}

P.S .: этот шаблон стоит только тогда, когда вам действительно нужно расширить класс BigDecimal, добавив кучу новых методов. Если вам просто нужно добавить только метод, лучше просто объявить где-нибудь статический метод, как предложено Энди Тернером .

0 голосов
/ 03 сентября 2018

Не расширять BigDecimal

BigDecimal класс не предназначен для переопределения . Класс должен быть помечен final, чтобы применить это ограничение в компиляторе, но, увы, он не был так помечен (неудачный недосмотр). Поэтому не переопределяйте BigDecimal.

Вы можете прочитать остальную часть моего Ответа, если думаете о других классах, кроме BigDecimal / BigInteger.

Полиморфизм

Узнайте о полиморфизме в Объектно-ориентированном программировании .

Если вы присваиваете ссылку на объект типа Dog на переменную типа суперкласса Animal, и ваш подкласс переопределяет метод eat, то вызов метода eat приводит к методу на подклассе выполняется. В этом и заключается магия позднего связывания или dynamic-dispatch (различные термины для этого поведения «найди правильное выполнение»).

Animal x = new Dog( … ) ;   // Polymorphism: Viewing a `Dog` object as an `Animal` object.
x.eat( … ) ;                // Results in Dog::eat method being invoked, *not* Animal::eat.

Предостережение: убедитесь, что ваш суперкласс и его методы предназначены для переопределения. Если помечено как final, это не так.

Нейминг

Совет. Следуйте соглашениям об именах. Класс всегда начинается с заглавной буквы. Используйте MySubClass, а не mySubClass в качестве имени класса.

...