Существует множество вопросов о невозможности включения статических абстрактных методов Java. Существует также много об обходных решениях для этого (недостаток дизайна/дизайн). Но я не могу найти какой-либо конкретной проблемы, о которой я расскажу в ближайшее время.
Мне кажется, что люди, которые создали Java и довольно много людей, которые его используют, не думают о статических методах, как я, и многие другие, - как функции класса или методы, которые принадлежат к классу, а не к какому-либо объекту. Итак, есть ли другой способ реализации функции класса?
Вот мой пример: в математике группа - это набор объектов, которые могут быть скомбинированы друг с другом с помощью некоторой операции * каким-то разумным способом - например, положительные действительные числа образуют группа при нормальном умножении (x * y = x × y), а множество целых чисел образуют группу, где операция умножения является добавлением (m * n = m + n).
Естественным способом моделирования этого в Java является определение интерфейса (или абстрактного класса) для групп:
public interface GroupElement
{
/**
/* Composes with a new group element.
/* @param elementToComposeWith - the new group element to compose with.
/* @return The composition of the two elements.
*/
public GroupElement compose(GroupElement elementToComposeWith)
}
Мы можем реализовать этот интерфейс для двух приведенных выше примеров:
public class PosReal implements GroupElement
{
private double value;
// getter and setter for this field
public PosReal(double value)
{
setValue(value);
}
@Override
public PosReal compose(PosReal multiplier)
{
return new PosReal(value * multiplier.getValue());
}
}
и
public class GInteger implements GroupElement
{
private int value;
// getter and setter for this field
public GInteger(double value)
{
setValue(value);
}
@Override
public GInteger compose(GInteger addend)
{
return new GInteger(value + addend.getValue());
}
}
Однако существует еще одно важное свойство, которое имеет группа: каждая группа имеет элемент identity - элемент e такой, что x * e = x для всех x в группе. Например, элемент идентификации для положительных чисел при умножении равен 1, а единичный элемент для целых чисел при добавлении равен 0. В этом случае имеет смысл иметь метод для каждого реализующего класса, например:
public PosReal getIdentity()
{
return new PosReal(1);
}
public GInteger getIdentity()
{
return new GInteger(0);
}
Но здесь мы сталкиваемся с проблемами - метод getIdentity
не зависит от какого-либо экземпляра объекта и поэтому должен быть объявлен static
(действительно, мы можем ссылаться на него из статического контекста). Но если мы поместим метод getIdentity
в интерфейс, мы не сможем объявить его static
в интерфейсе, поэтому он не может быть static
в любом классе реализации.
Есть ли способ реализовать этот метод getIdentity
, который:
- Сила согласования во всех реализациях
GroupElement
, поэтому каждая реализацияGroupElement
должна включать функциюgetIdentity
. - Поведение статически; то есть мы можем получить элемент идентификации для данной реализации
GroupElement
без создания экземпляра объекта для этой реализации.
Условие (1) по существу говорит "абстрактно", а условие (2) говорит "статично", и я знаю, что static
и abstract
несовместимы в Java. Итак, есть ли некоторые связанные понятия на языке, который можно использовать для этого?