java interface
Привет всем.
у меня такой вопрос.
есть интерфейс:
public interface TestInterface {}
есть два класса, которые его имплементируют:
public class A implements TestInterface{
public A(BigInteger value){
System.out.println("This is A");
}
}
public class B implements TestInterface{
public B(BigDecimal value){
System.out.println("This is B");
}
}
Нужно что бы в зависимости от параметра (тут BigInteger и BigDecimal) создавался конкретный объект.
Что то типа TestInterface ti = new TestInterface(BigInteger bi){}
Это возможно сделать? если да то как?
Я не знаю, на сколько могут отличаться классы А от В, но чисто по описанию я бы реализовал через Generic.
кстати тоже хороший способ. Но у меня будет не только A и B. У меня будет A,B,C,D,E классы.
А вообще мне идея с интерфейсом не очень нравится, тк все классы имеют свои методы, которые в других классах не существуют. Но это идея бетроера. Завтра буду говорить с ним по этому поводу
Я поговорил сегодня с Бетроером. Он против dependency injection, говорит что это может повлиять на всю систему. И ему подходит вариант с factory. Но мне не нравится то, что интерфейс будет содержать все методы из всех классов. Например класс A должен будет реализовать методы, которые ему не нужны, а нужны классу B.
У Бетроера что очередная параноя на базе ДИ?
https://msdn.microsoft.com/en-us/library/aa288059(v=vs.71)...
Как может номер "привязанный" к классу развалить систему и где он там ДИ увидел? В спецочках наверное.
Не, если очень постарться то можно всё сделать, но это надо сильно стараться
Но мне не нравится то, что интерфейс будет содержать все методы из всех классов
Нафига? Интерфес общий, а имплементации различные.
Если нужно в интерфейс выкидывать все методы, то необходимо срочно искать другого Бетроера.
получается, что класс A и B содержат ненужные методы, тк эти методы в интерфейсе. Классам же на верху (SomethingA, SomethingB) нужны только определенные методы. Но эти классы должны знать только интерфейс.
Есть какое-то разумное решение у этой проблемы?
Ps uml набросал на коленке. Извиняюсь за качество
Тогда, как вариант: пишете еще одну архитектуру классов, т.е. интерфейс и реализации для "параметров", вроде IParameters, ParameterA, ParameterB,... Тогда в методе do для классов A,B,C,...будет один аргумент типа IParam, ну а каждая из реализаций будет использовать свою реализацию параметров ParameterA,...
Я если честно уже не уверен, что мне делать
Если не уверены, то нужно делать как шеф хочет, только чтобы было в письменной форме, без всяких вариантов - "а Вы меня не так поняли"
По идее он хочет абстрактную фабрику классов.
https://refactoring.guru/ru/design-patterns/abstract-facto...
https://en.wikipedia.org/wiki/Factory_method_pattern
http://www.oodesign.com/factory-method-pattern.html
методы могут быть разные с разными параметрами.
Понятно... архитектура от того же "Бетроера"
Тогда самое простое, как уже написали: добавляем промежуточный класс/интерфейс для списка параметров. И его пользуем вместо списка различных параметров.
Было бы неплохо поконкретнее описать ваши А,Б, что делает doA, что - doB.
А то пока что под ваше описание подходит интерфейс, скажем List. doA это add(Object), doB это get(int), и реализации - ArrayList и LinkedList. SomethingA в список добавляет, SomethingB - читает. Всё разумно.
Generic можно было бы использовать, если бы методы были одинаковые.
public interface TestInterface<T> {
public void a(T value);
}
public class TestImplA implements TestInterface<BigInteger> {
@Override
public void a(BigInteger value) { }}
Но тут названия методов отличаются, в первом случае А, а во втором - B:
public class A implements TestInterface{
public A(BigInteger value){
System.out.println("This is A");
}
}public class B implements TestInterface{
public B(BigDecimal value){
System.out.println("This is B");
}
}
Архитектура явно кривая, грубо нарушено Single Responsibility Rule, классы огромные итд. Необходимо разбить интерфейс на несколько, с использованием дженериков, выделить отдельные классы и так далее. Толку от использования общего интерфейса, если методы все равно разные, и по идее впоследствии в коде нужно будет делать проверки при их вызове в зависимости от аргумента?
TestInterface worker = TestInterfaceFactory.getTestInterface(value);
if (value instanceof BigInteger) {
worker.a(value);
} elseif (value instanceof BigDecimal) {
worker.b(value);
} else {
...
Но в любом разе решение - это фабрика:
public class TestInterfaceFactory {
public static TestInterface getInstance(Object value) {if (value instanceof BigInteger) {return new TestImplA();} else if (value instanceof BigDecimal) {return new TestImplB();} else {throw new IllegalArgumentException("unsopported value type");}}}
вот что я пока написал только для одного класса:
1) интерфейс
public interface NumberInterface {
public NumberInterface EMPTY();
public NumberInterface UNBOUND();
public NumberInterface BOOLEAN_INTERVAL();
public NumberInterface ZERO();
public NumberInterface ONE();
public boolean intersects(NumberInterface other);
public Number getLow();
public Number getHigh();
public boolean isGreaterThan(NumberInterface other);
public boolean isGreaterOrEqualThan(NumberInterface other);
public NumberInterface plus(NumberInterface interval);
public NumberInterface minus(NumberInterface other);
public NumberInterface times(NumberInterface other);
public NumberInterface divide(NumberInterface other);
public NumberInterface shiftLeft(NumberInterface offset);
public NumberInterface shiftRight(NumberInterface offset);
public NumberInterface modulo(NumberInterface other);
public boolean isUnbound();
public NumberInterface union(NumberInterface other) ;
public boolean contains(NumberInterface other);
public boolean isEmpty();
public NumberInterface negate();
// public
NumberInterface createUpperBoundedInterval(Long upperBound);
// public NumberInterface createLowerBoundedInterval(Long lowerBound);
public NumberInterface intersect(NumberInterface other);
public NumberInterface limitUpperBoundBy(NumberInterface other);
public NumberInterface limitLowerBoundBy(NumberInterface other);
}
класс который его имплеменитирует
public class IntegerInterval implements NumberInterface {
/**
* the lower bound of the interval
*/
private final Long low;
/**
* the upper bound of the interval
*/
private final Long high;
private static final IntegerInterval EMPTY = new IntegerInterval(null, null);
public static final IntegerInterval UNBOUND = new IntegerInterval(Long.MIN_VALUE, Long.MAX_VALUE);
public static final IntegerInterval BOOLEAN_INTERVAL = new IntegerInterval(0L, 1L);
public static final IntegerInterval ZERO = new IntegerInterval(0L, 0L);
public static final IntegerInterval ONE = new IntegerInterval(1L, 1L);
/**
* This method acts as constructor for a single-value interval.
*
* @param value
* for the
lower and upper bound
*/
public IntegerInterval(Long value) {
this.low = value;
this.high = value;
isSane();
}
/**
* This method acts as constructor for a long-based interval.
*
* @param low
* the lower bound
* @param high
* the upper bound
*/
public IntegerInterval(Long low, Long high) {
this.low = low;
this.high = high;
isSane();
}
@Override
public NumberInterface EMPTY() {
return EMPTY;
}
@Override
public NumberInterface UNBOUND() {
return UNBOUND;
}
@Override
public NumberInterface BOOLEAN_INTERVAL() {
return BOOLEAN_INTERVAL;
}
@Override
public NumberInterface ZERO() {
return ZERO;
}
@Override
public NumberInterface ONE() {
return ONE;
}
private boolean isSane() {
if ((low == null) != (high == null)) {
throw new IllegalStateException("invalid empty interval");
}
if (low != null && low > high) {
throw new IllegalStateException("low cannot be larger than high");
}
return true;
}
/**
* This method returns the lower bound of the interval.
*
* @return the lower bound
*/
@Override
public Long getLow() {
return low;
}
/**
* This method returns the upper bound of the interval.
*
* @return the upper bound
*/
@Override
public Long getHigh() {
return high;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object other) {
if (other != null && getClass().equals(other.getClass())) {
IntegerInterval another = (IntegerInterval) other;
return Objects.equals(low, another.getLow()) && Objects.equals(high, another.getHigh());
}
return false;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(low, high);
}
/**
* This method creates
a new interval instance representing the union of
* this interval with another interval.
*
* The lower bound and upper bound of the new interval is the minimum of
* both lower bounds and the maximum of both upper bounds, respectively.
*
* @param other
* the other interval
* @return the new interval with the respective bounds
*/
@Override
public NumberInterface union(NumberInterface other) {
IntegerInterval tempOther = (IntegerInterval)other;
if (isEmpty() || tempOther.isEmpty()) {
return EMPTY;
} else if (low <= other.getLow() && high >= other.getHigh()) {
return this;
} else if (low >= other.getLow() && high <= other.getHigh()) {
return other;
} else {
return new IntegerInterval(Math.min(low, other.getLow()), Math.max(high, other.getHigh()));
}
}
/**
* This method creates a new interval instance representing the intersection
* of this interval with another interval.
*
* The lower bound and upper bound of the new interval is the maximum of
* both lower bounds and the minimum of both upper bounds, respectively.
*
* @param other
* the other interval
* @return the new interval with the respective bounds
*/
@Override
public NumberInterface intersect(NumberInterface other) {
if (this.intersects(other)) {
return new IntegerInterval(Math.max(low, other.getLow()), Math.min(high, other.getHigh()));
} else {
return
EMPTY;
}
}
/**
* This method determines if this interval is definitely greater than the
* other interval.
*
* @param other
* interval to compare with
* @return true if the lower bound of this interval is always strictly
* greater than the upper bound of the other interval, else false
*/
@Override
public boolean isGreaterThan(NumberInterface other) {
IntegerInterval tempOther = (IntegerInterval)other;
return !isEmpty() && !tempOther.isEmpty() && low > tempOther.getHigh();
}
/**
* This method determines if this interval is definitely greater or equal
* than the other interval. The equality is only satisfied for one
single
* value!
*
* @param other
* interval to compare with
* @return true if the lower bound of this interval is always strictly
* greater or equal than the upper bound of the other interval, else
* false
*/
@Override
public boolean isGreaterOrEqualThan(NumberInterface other) {
IntegerInterval tempOther = (IntegerInterval)other;
return !isEmpty() && !tempOther.isEmpty() && low >= tempOther.getHigh();
}
/**
* This method determines if this interval maybe greater than the other
* interval.
*
* @param other
* interval to compare with
* @return true if the upper bound of this interval is strictly greater than
* the lower bound of the other interval, else false
*/
public boolean mayBeGreaterThan(IntegerInterval other) {
return other.isEmpty() || (!isEmpty() && !other.isEmpty() && high > other.getLow());
}
/**
* This method determines if this interval maybe greater or equal than the
* other interval.
*
* @param other
* interval to compare with
* @return true if the upper bound of this interval is strictly greater than
* the lower bound of the other interval, else false
*/
public boolean mayBeGreaterOrEqualThan(IntegerInterval other) {
return other.isEmpty() || (!isEmpty() && !other.isEmpty() && high >= other.getLow());
}
/**
* New interval
instance after the modulo computation.
*
* @param other
* the other interval
* @return the new interval with the respective bounds.
*/
@Override
public NumberInterface modulo(NumberInterface other){
IntegerInterval tempOther = (IntegerInterval)other;
if (tempOther.contains(ZERO)) {
return IntegerInterval.UNBOUND;
}
// The interval doesn't contain zero, hence low and high has to be of
// the same sign.
// In that case we can call an absolute value on both, as "% (-x)" is
// the same as "% x".
other = new IntegerInterval(Math.abs(other.getLow()), Math.abs(other.getHigh()));
long newHigh;
long newLow;
// New high of the interval can't be higher than
the highest value in
// the divisor.
// If the divisible element is positive, it is also bounded by it's
// highest number,
// or by the absolute value of the lowest number.
// (-1 % 6 CAN be either -1 or 5 according to the C standard).
long top;
if (low >= 0) {
top = high;
} else {
if (low == Long.MIN_VALUE) {
top = Long.MAX_VALUE;
} else {
top = Math.max(Math.abs(low), high);
}
}
newHigh = Math.min(top, other.getHigh() - 1);
// Separate consideration for the case where the divisible number can be
// negative.
if
(low >= 0) { // If the divisible interval is all positive, the lowest
// we can ever get is 0.
// We can only get zero if we include 0 or the number higher than
// the smallest value of the other interval.
if (low == 0 || high >= other.getLow()) {
newLow = 0;
} else {
newLow = low;
}
} else {
// The remainder can go negative, but it can not be more negative
// than the negation of the highest value
// of the other interval plus 1.
// (e.g. X mod 14 can not be lower than -13)
// Remember, <low> is negative in this branch.
newLow = Math.max(low, 1 - other.getHigh());
}
IntegerInterval out = new IntegerInterval(newLow, newHigh);
return out;
}
/**
* This method returns a new interval with a limited, i.e. higher, lower
* bound.
*
* @param other
* the interval to limit this interval
* @return the new interval with the upper bound of this interval and the
* lower bound set to the maximum of this interval's and the other
* interval's lower bound or an empty interval if this interval is
* less than the other interval.
*/
@Override
public NumberInterface limitLowerBoundBy(NumberInterface other) {
IntegerInterval interval = null;
if (isEmpty() || other.isEmpty() || high < other.getLow()) {
interval = EMPTY;
} else {
interval = new IntegerInterval(Math.max(low, other.getLow()), high);
}
return interval;
}
/**
* This method returns a new interval with a limited, i.e. lower, upper
* bound.
*
* @param other
* the interval to limit this interval
* @return the new interval with the lower bound of this interval and the
* upper bound set to the minimum of this interval's and the other
* interval's upper bound or an empty interval if this
interval is
* greater than the other interval.
*/
@Override
public NumberInterface limitUpperBoundBy(NumberInterface other) {
IntegerInterval interval = null;
if (isEmpty() || other.isEmpty() || low > other.getHigh()) {
interval = EMPTY;
} else {
interval = new IntegerInterval(low, Math.min(high, other.getHigh()));
}
return interval;
}
/**
* This method determines if this interval intersects with another interval.
*
* @param other
* the other interval
* @return true if the intervals intersect, else false
*/
@Override
public boolean intersects(NumberInterface other) {
if (isEmpty() || other.isEmpty()) {
return false;
}
return
(low >= other.getLow() && low <= other.getHigh()) || (high >= other.getLow() && high <= other.getHigh())
|| (low <= other.getLow() && high >= other.getHigh());
}
/**
* This method determines if this interval contains another interval.
*
* The method still returns true, if the borders match. An empty interval
* does not contain any interval and is not contained in any interval
* either. So if the callee or parameter is an empty interval, this method
* will return false.
*
* @param other
* the other interval
* @return true if this interval contains the other interval, else false
*/
@Override
public boolean contains(NumberInterface other) {
IntegerInterval tempOther = (IntegerInterval)other;
return (!isEmpty() && !tempOther.isEmpty() && low <= other.getLow() && other.getHigh() <= high);
}
/**
* This method adds an interval from this interval, overflow is handled by
* setting the bound to Long.MIN_VALUE or Long.MAX_VALUE respectively.
*
* @param interval
* the interval to add
* @return a new interval with the respective bounds
*/
@Override
public NumberInterface plus(NumberInterface interval) {
IntegerInterval tempInterval = (IntegerInterval)interval;
if (isEmpty() || tempInterval.isEmpty()) {
return EMPTY;
}
return new IntegerInterval(scalarPlus(low, tempInterval.getLow()), scalarPlus(high, tempInterval.getHigh()));
}
/**
* This method adds a
constant offset to this interval, overflow is handled
* by setting the bound to Long.MIN_VALUE or Long.MAX_VALUE respectively.
*
* @param offset
* the constant offset to add
* @return a new interval with the respective bounds
*/
public NumberInterface plus(Long offset) {
return plus(new IntegerInterval(offset, offset));
}
/**
* This method subtracts an interval from this interval, overflow is handled
* by setting the bound to Long.MIN_VALUE or Long.MAX_VALUE respectively.
*
* @param other
* interval to subtract
* @return a new interval with the respective bounds
*/
@Override
public NumberInterface minus(NumberInterface other) {
IntegerInterval tempOther =
(IntegerInterval)other;
return plus(tempOther.negate());
}
/**
* This method subtracts a constant offset to this interval, overflow is
* handled by setting the bound to Long.MIN_VALUE or Long.MAX_VALUE
* respectively.
*
* @param offset
* the constant offset to subtract
* @return a new interval with the respective bounds
*/
public NumberInterface minus(Long offset) {
return plus(-offset);
}
/**
* This method multiplies this interval with another interval. In case of an
* overflow Long.MAX_VALUE and Long.MIN_VALUE are used instead.
*
* @param other
* interval to multiply this interval with
* @return new interval that represents
the result of the multiplication of
* the two intervals
*/
@Override
public NumberInterface times(NumberInterface other) {
Long[] values = { scalarTimes(low, other.getLow()), scalarTimes(low, other.getHigh()),
scalarTimes(high, other.getLow()), scalarTimes(high, other.getHigh()) };
return new IntegerInterval(Collections.min(Arrays.asList(values)), Collections.max(Arrays.asList(values)));
}
/**
* This method divides this interval by another interval. If the other
* interval contains "0" an unbound interval is returned.
*
* @param other
* interval to divide this interval by
* @return new interval that represents the result of the division of the
* two intervals
*/
@Override
public NumberInterface divide(NumberInterface other) {
// other interval
contains "0", return unbound interval
if (other.contains(ZERO)) {
return UNBOUND;
} else {
Long[] values = { low / other.getLow(), low / other.getHigh(), high / other.getLow(),
high / other.getHigh() };
return new IntegerInterval(Collections.min(Arrays.asList(values)), Collections.max(Arrays.asList(values)));
}
}
/**
* This method performs an arithmetical left shift of the interval bounds.
*
* @param offset
* Interval offset to perform an arithmetical left shift on the
* interval bounds. If the offset maybe less than zero an unbound
* interval is returned.
* @return new interval that represents the result of the arithmetical left
* shift
*/
@Override
public
NumberInterface shiftLeft(NumberInterface offset) {
// create an unbound interval upon trying to shift by a possibly
// negative offset
IntegerInterval tempOffset = (IntegerInterval)offset;
if (ZERO.mayBeGreaterThan(tempOffset)) {
return UNBOUND;
} else {
// if lower bound is negative, shift it by upper bound of offset,
// else by lower bound of offset
Long newLow = low << ((low < 0L) ? offset.getHigh() : offset.getLow());
// if upper bound is negative, shift it by lower bound of offset,
// else by upper bound of offset
Long newHigh = high << ((high < 0L) ? offset.getLow() : offset.getHigh());
if ((low < 0 && newLow > low) ||
(high > 0 && newHigh < high)) {
return UNBOUND;
} else {
return new IntegerInterval(newLow, newHigh);
}
}
}
/**
* This method performs an arithmetical right shift of the interval bounds.
* If the offset maybe less than zero an unbound interval is returned.
*
* @param offset
* Interval offset to perform an arithmetical right shift on the
* interval bounds
* @return new interval that represents the result of the arithmetical right
* shift
*/
@Override
public NumberInterface shiftRight(NumberInterface offset) {
// create an unbound interval upon trying to shift by a possibly
//
negative offset
IntegerInterval tempOffset = (IntegerInterval)offset;
if (ZERO.mayBeGreaterThan(tempOffset)) {
return UNBOUND;
} else {
// if lower bound is negative, shift it by lower bound of offset,
// else by upper bound of offset
Long newLow = low >> ((low < 0L) ? offset.getLow() : offset.getHigh());
// if upper bound is negative, shift it by upper bound of offset,
// else by lower bound of offset
Long newHigh = high >> ((high < 0L) ? offset.getHigh() : offset.getLow());
return new IntegerInterval(newLow, newHigh);
}
}
/**
* This method negates this interval.
*
* @return new negated interval
*/
@Override
public NumberInterface negate() {
return new IntegerInterval(scalarTimes(high, -1L), scalarTimes(low, -1L));
}
/**
* This method determines whether the interval is empty or not.
*
* @return true, if the interval is empty, i.e. the lower and upper bounds
* are null
*/
@Override
public boolean isEmpty() {
return low == null && high == null;
}
@Override
public boolean isUnbound() {
return !isEmpty() && low == Long.MIN_VALUE && high == Long.MAX_VALUE;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "[" + (low
== null ? "" : low) + "; " + (high == null ? "" : high) + "]";
}
/**
* This method is a factory method for a lower bounded interval.
*
* @param lowerBound
* the lower bound to set
* @return a lower bounded interval, i.e. the lower bound is set to the
* given lower bound, the upper bound is set to Long.MAX_VALUE
*/
public static NumberInterface createLowerBoundedInterval(Long lowerBound) {
return new IntegerInterval(lowerBound, Long.MAX_VALUE);
}
/**
* This method is a factory method for an upper bounded interval.
*
* @param upperBound
* the
upper bound to set
* @return an upper bounded interval, i.e. the lower bound is set to
* Long.MIN_VALUE, the upper bound is set to the given upper bound
*/
public static NumberInterface createUpperBoundedInterval(Long upperBound) {
return new IntegerInterval(Long.MIN_VALUE, upperBound);
}
/**
* This method adds two scalar values and returns their sum, or on overflow
* Long.MAX_VALUE or Long.MIN_VALUE, respectively.
*
* @param x
* the first scalar operand
* @param y
* the second scalar operand
* @return the sum of the first and second scalar operand or on overflow
* Long.MAX_VALUE and Long.MIN_VALUE, respectively.
*/
private
static Long scalarPlus(Long x, Long y) {
Long result = x + y;
// both operands are positive but the result is negative
if ((Long.signum(x) + Long.signum(y) == 2) && Long.signum(result) == -1) {
result = Long.MAX_VALUE;
} else if ((Long.signum(x) + Long.signum(y) == -2) && Long.signum(result) == +1) {
result = Long.MIN_VALUE;
}
return result;
}
/**
* This method multiplies two scalar values and returns their product, or on
* overflow Long.MAX_VALUE or Long.MIN_VALUE, respectively.
*
* @param x
* the first scalar operand
* @param y
* the second scalar operand
* @return the product
of the first and second scalar operand or on overflow
* Long.MAX_VALUE and Long.MIN_VALUE, respectively.
*/
private static Long scalarTimes(Long x, Long y) {
Long bound = (Long.signum(x) == Long.signum(y)) ? Long.MAX_VALUE : Long.MIN_VALUE;
// if overflow occurs, return the respective bound
if (x != 0 && ((y > 0 && y > (bound / x)) || (y < 0 && y < (bound / x)))) {
return bound;
} else {
return x * y;
}
}
}
class ExpressionValueVisitor extends DefaultCExpressionVisitor<NumberInterface, UnrecognizedCCodeException>
implements CRightHandSideVisitor<NumberInterface, UnrecognizedCCodeException> {
private final IntervalAnalysisState readableState;
private final CFAEdge cfaEdge;
public ExpressionValueVisitor(IntervalAnalysisState pState, CFAEdge edge) {
readableState = pState;
cfaEdge = edge;
}
@Override
protected NumberInterface visitDefault(CExpression expression) {
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
}
@Override
public NumberInterface visit(CBinaryExpression binaryExpression) throws UnrecognizedCCodeException {
NumberInterface interval1 = binaryExpression.getOperand1().accept(this);
NumberInterface interval2 = binaryExpression.getOperand2().accept(this);
if (interval1 == null || interval2 == null) {
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
}
BinaryOperator operator = binaryExpression.getOperator();
if (operator.isLogicalOperator()) {
return getLogicInterval(operator, interval1, interval2);
} else {
return getArithmeticInterval(operator, interval1, interval2);
}
}
private static NumberInterface getLogicInterval(
BinaryOperator operator, NumberInterface interval1, NumberInterface interval2) {
switch (operator) {
case EQUALS:
if (!interval1.intersects(interval2)) {
return new CreatorIntegerInterval().factoryMethod(null).ZERO();
} else if (interval1.getLow().equals(interval1.getHigh()) && interval1.equals(interval2)) {
// singular interval, [5;5]==[5;5]
return new CreatorIntegerInterval().factoryMethod(null).ONE();
} else {
return new CreatorIntegerInterval().factoryMethod(null).BOOLEAN_INTERVAL();
}
case NOT_EQUALS:
if (!interval1.intersects(interval2)) {
return new CreatorIntegerInterval().factoryMethod(null).ONE();
} else if (interval1.getLow().equals(interval1.getHigh()) && interval1.equals(interval2)) {
// singular interval, [5;5]!=[5;5]
return new CreatorIntegerInterval().factoryMethod(null).ZERO();
} else {
return new CreatorIntegerInterval().factoryMethod(null).BOOLEAN_INTERVAL();
}
case GREATER_THAN:
if (interval1.isGreaterThan(interval2)) {
return new CreatorIntegerInterval().factoryMethod(null).ONE();
} else if (interval2.isGreaterOrEqualThan(interval1)) {
return new CreatorIntegerInterval().factoryMethod(null).ZERO();
} else {
return new CreatorIntegerInterval().factoryMethod(null).BOOLEAN_INTERVAL();
}
case GREATER_EQUAL: // a>=b == a+1>b, works only for integers
return getLogicInterval(
BinaryOperator.GREATER_THAN, interval1.plus(new CreatorIntegerInterval().factoryMethod(null).ONE()), interval2);
case LESS_THAN: // a<b == b>a
return getLogicInterval(BinaryOperator.GREATER_THAN, interval2, interval1);
case LESS_EQUAL: // a<=b == b+1>a, works only for integers
return getLogicInterval(
BinaryOperator.GREATER_THAN, interval2.plus(new CreatorIntegerInterval().factoryMethod(null).ONE()), interval1);
default:
throw new AssertionError("unknown binary operator: " + operator);
}
}
private static NumberInterface getArithmeticInterval(
BinaryOperator operator, NumberInterface interval1, NumberInterface interval2) {
switch (operator) {
case PLUS:
return interval1.plus(interval2);
case MINUS:
return interval1.minus(interval2);
case MULTIPLY:
return interval1.times(interval2);
case DIVIDE:
return
interval1.divide(interval2);
case SHIFT_LEFT:
return interval1.shiftLeft(interval2);
case SHIFT_RIGHT:
return interval1.shiftRight(interval2);
case MODULO:
return interval1.modulo(interval2);
case BINARY_AND:
case BINARY_OR:
case BINARY_XOR:
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
default:
throw new AssertionError("unknown binary operator: " + operator);
}
}
@Override
public NumberInterface visit(CCastExpression cast) throws UnrecognizedCCodeException {
return cast.getOperand().accept(this);
}
@Override
public NumberInterface visit(CFunctionCallExpression functionCall) {
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
}
@Override
public NumberInterface visit(CCharLiteralExpression charLiteral) {
return new CreatorIntegerInterval().factoryMethod((long) charLiteral.getCharacter());
}
@Override
public NumberInterface visit(CImaginaryLiteralExpression exp) throws UnrecognizedCCodeException {
return exp.getValue().accept(this);
}
@Override
public NumberInterface visit(CIntegerLiteralExpression integerLiteral) {
//TODO BigInteger
return new CreatorIntegerInterval().factoryMethod(integerLiteral.asLong());
}
@Override
public NumberInterface visit(CFloatLiteralExpression integerLiteral) {
//TODO BigDecimal
return new CreatorIntegerInterval().factoryMethod(integerLiteral.getValue().longValue());
}
@Override
public NumberInterface visit(CIdExpression identifier) {
if (identifier.getDeclaration() instanceof CEnumerator) {
//TODO WTF
return new CreatorIntegerInterval().factoryMethod(((CEnumerator) identifier.getDeclaration()).getValue());///???
}
final String variableName = identifier.getDeclaration().getQualifiedName();
if (readableState.contains(variableName)) {
return readableState.getInterval(variableName);
} else {
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
}
}
@Override
public NumberInterface visit(CUnaryExpression unaryExpression) throws UnrecognizedCCodeException {
NumberInterface interval = unaryExpression.getOperand().accept(this);
switch (unaryExpression.getOperator()) {
case MINUS:
return interval.negate();
case AMPER:
case TILDE:
return new CreatorIntegerInterval().factoryMethod(null).UNBOUND();
// valid expression, but it's a pointer value
default:
throw new UnrecognizedCCodeException("unknown unary operator", cfaEdge, unaryExpression);
}
}
}
а вот собственно класс который вызывает интерфейс. таких классов три, каждый что то свое вызывает. в данном случае интервалы
Как там у вас я Яве принято не знаю.
Но константантам в интерфейсе по идее нечего делать.
public NumberInterface EMPTY(); public NumberInterface UNBOUND(); public NumberInterface BOOLEAN_INTERVAL(); public NumberInterface ZERO(); public NumberInterface ONE();
ну и не принято вроде, чтобы IsXxxx выбрасывала исключение.