-
Notifications
You must be signed in to change notification settings - Fork 3
/
AbstractBoolVect.java
192 lines (168 loc) · 7.36 KB
/
AbstractBoolVect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
Copyright 2022 Massimo Santini
This file is part of "Programmazione 2 @ UniMI" teaching material.
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This material is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file. If not, see <https://www.gnu.org/licenses/>.
*/
import java.util.Objects;
/**
* Classe astratta che provvede l'implementazione di alcuni dei metodi dell'inferfaccia {@link
* BoolVect}.
*
* <p>Questa classe implementa i metodi totali {@link BoolVect#leggi(int)} e {@link
* BoolVect#scrivi(int, boolean)} grazie ai metodi parziali {@link #leggiParziale(int)} e {@link
* #scriviParziale(int, boolean)} che devono essere implementati dalle sue sottoclassi; il vantaggio
* è che le sottoclassi, potendo evitare i controlli sulla posizione, potranno fornire una
* implementazione molto snella.
*
* <p>Implementa inoltre i metodi {@link BoolVect#and(BoolVect)}, {@link BoolVect#or(BoolVect)} e
* {@link BoolVect#xor(BoolVect)} a partire dagli operatori booleani definiti in base
* all'interfaccia {@link AbstractBoolVect.BooleanOperator}, grazie alla funzione {@link
* #componenteAComponente(BooleanOperator, BoolVect)} che li estende componente a componente.
*
* <p>Infine, provvede una implementazione elementare di {@link #toString()} ed una molto
* inefficiente per {@link #equals(Object)}, le sottoclassi concrete devono implementare se
* possibile una versione ottimizzata di tale medoto, ma in ogni caso una versione coerente di
* {@link Object#hashCode()}.
*/
public abstract class AbstractBoolVect implements BoolVect {
/* Implementaizone dei metodi leggi e scrivi attraverso i corrispondenti non totali */
/**
* Funzione parziale che restituisce il valore di verità di posizione specificata.
*
* @param pos la posizione, deve essere compresa tra 0 (incluso) e la taglia (esclusa).
* @return il valore di verità.
*/
protected abstract boolean leggiParziale(final int pos);
/**
* Funzione parziale che scrive il valore di verità dato nella posizione specificata.
*
* @param pos la posizione, deve essere compresa tra 0 (incluso) e la taglia (esclusa).
* @param val il valore.
*/
protected abstract void scriviParziale(final int pos, final boolean val);
@Override
public boolean leggi(final int pos) throws IndexOutOfBoundsException {
if (pos < 0) throw new IndexOutOfBoundsException("La posizione non può essere negativa.");
return pos < dimensione() ? leggiParziale(pos) : false;
}
@Override
public void scrivi(final int pos, final boolean val) throws IndexOutOfBoundsException {
if (pos < 0) throw new IndexOutOfBoundsException("La posizione non può essere negativa.");
if (pos >= taglia() && val)
throw new IndexOutOfBoundsException(
"Non è possibile scrivere un valore di verità vero in posizione maggiore o uguale alla taglia.");
scriviParziale(pos, val);
}
/* Implementazione delle operazioni booleane, tramite l'introduzione di una
* interfaccia per parametrizzare la costruzione della versione componente a
* componente.
*/
/** Interfaccia che descrive l'applicazoine di un operatore logico binario questo BoolVect. */
public interface BooleanOperator {
boolean apply(final boolean a, final boolean b);
}
/**
* Metodo parziale che, dato un operatore booleano e un BoolVect applica l'operazione componente a
* componente ottenuta dall'operatore booleano a questo e il BoolVect dato e ne salva il risultato
* in questo.
*
* <p>Gli argomenti non devono essere {@code null} (questa è una funzione parziale).
*
* @param op l'operatore booleano.
* @param other il primo BoolVect.
*/
public void componenteAComponente(BooleanOperator op, BoolVect other)
throws IndexOutOfBoundsException {
final int dimensioneMax = Math.max(dimensione(), other.dimensione());
for (int pos = 0; pos <= dimensioneMax; pos++)
scrivi(pos, op.apply(leggi(pos), other.leggi(pos)));
}
@Override
public void and(final BoolVect other) throws NullPointerException {
componenteAComponente(
new BooleanOperator() {
@Override
public boolean apply(boolean a, boolean b) {
return a & b;
}
},
Objects.requireNonNull(other, "L'argomento non può essere null."));
}
@Override
public void or(final BoolVect other) throws NullPointerException, IllegalArgumentException {
try {
componenteAComponente(
new BooleanOperator() {
@Override
public boolean apply(boolean a, boolean b) {
return a | b;
}
},
Objects.requireNonNull(other, "L'argomento non può essere null."));
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"La taglia di questo vettore è minore della dimensione del risultato.");
}
}
@Override
public void xor(final BoolVect other) throws NullPointerException, IllegalArgumentException {
try {
componenteAComponente(
new BooleanOperator() {
@Override
public boolean apply(boolean a, boolean b) {
return a ^ b;
}
},
Objects.requireNonNull(other, "L'argomento non può essere null."));
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"La taglia di questo vettore è minore della dimensione del risultato.");
}
}
/* Implementazione non specializzata dei metodi ereditati da {@code Object}. */
/**
* Restituisce la versione stringa di questo BoolVect.
*
* <p>Se la dimensione del BoolVect è 0 restituisce "F", altrimenti restituisce una stringa che
* comprende un numero di caratteri pari alla dimensione del BoolVect, detto altrimenti i valori
* di verità {@code false} che hanno posizione maggiore della dimensione non sono parte della
* stringa; l'<em>i</em>-esimo carattere della stringa (contando da destra) è `V` se
* l'<em>i</em>-esima posizione del BoolVect ha valore di verità {@code true}, o `F` se vale
* {@code false}.
*
* @return la stringa corrispondente a questo BoolVect.
*/
@Override
public String toString() {
if (dimensione() == 0) return "F";
final StringBuilder b = new StringBuilder();
for (int i = dimensione() - 1; i >= 0; i--) b.append(leggiParziale(i) ? 'V' : 'F');
return b.toString();
}
/**
* Implementazione non specializzata di equals.
*
* <p>Questa implementazione è molto inefficiente per il caso sparso; le sottoclassi dovrebbero
* implementare una versione ottimizzata e in ogni caso sovrascrivere {@link Object#hashCode()} in
* modo coerente.
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BoolVect)) return false;
BoolVect altro = (BoolVect) obj;
if (dimensione() != altro.dimensione()) return false;
for (int i = dimensione() - 2; i >= 0; i--) // a dimensione() - 1 sono entrambi true
if (leggi(i) != altro.leggi(i)) return false;
return true;
}
}