#Voto: 28
Tutte le azioni non permesse come:
- ridefinizione di classi già esistenti;
- definizione di field con valori non accettati dal suo tipo;
- chiamate fatte in modo errato,
- dichiarare un field che ha come tipo la classe che si sta dichiarando al momento
- dichiarare un field che ha un tipo incompatibile con quello del field della superclasse
ritorneranno false
.
Il programma rispetta i concetti base del polimorfismo e accetta come parametro nella maggiorparte dei predicati sia il nome dell'istanza sia l'oggetto stesso che la rappresenta
- E' possibile ridefinire le istanze;
- E' possibile avere più classi padre;
- E' possibile specificare o omettere il tipo nei fields;
- Il tipo
string
accetta stringhe sia denotate da'
che da"
; - Il tipo
float
accetta anche valori interi (42
e3.14
); - Il tipo
any
accetta qualsiasi tipo di valore; - Il valore
nil
è accettato da tutti i tipi; - I tipi dei fields possono essere nomi di classi definite;
- E' possibile passare più argomenti nei metodi creati.
Quando si definisce una nuova classe e si dichiara un field con nome già esistente, il nuovo field è accettato in questi casi:
- Se il tipo del field della superclasse non è specificato o è
any
- Se il tipo del field della superclasse e il nuovo tipo corrispondono
- Se il tipo del field della superclasse è un
float
e il nuovo tipo è uninteger
- Se il tipo del field della superclasse è una classe
X
e il nuovo tipo è una sottoclasse diX
-
Per definire una classe si può utilizzare
def_class/2
odef_class/3
Definiamo una classe di nomepersona
, senza parents, fields e metodi:?- def_class(persona, []).
-
Definiamo una classe di nome
studente
conpersona
come superclasse e con dei fields e dei metodi:?- def_class(studente, [persona], [field(name, 'Francesco', string), field(university, 'Bicocca'), field(container, nil, studente), method(talk, [], (write('il mio nome è'), field(this, name, N), writeln(N), write('la mia università è'), field(this, university, U), writeln(U)) ) ] ).
-
E' possibile richiamare il metodo
talk
appena creato in questo modo:?- talk(oggettoistanza).
In questo caso non abbiamo specificato alcun argomento da passare al metodo.
-
Per definire una nuova istanza si può utilizzare
make/2
omake/3
. Definiamo un'istanza di tipostudente
di nomemario
.?- make(mario, studente).
-
Per specificare dei field all'istanza si può usare
make/3
.?- make(giulia, studente, [university = 'UNIMI']).
-
Come richiesto da consegna, è possibile anche passare come primo parametro a
make/3
una variabile che unifica con l'istanza creata, ma questa istanza non verrà aggiunta alla base di conoscenza.?- make(X, studente, []). X = stored_instance(X, studente. []).
-
Come richiesto da consegna, è possibile anche passare come primo parametro a
make/3
un termine che rappresenta l'istanza, anche questa non verrà aggiunta alla base di conoscenza.?- make(stored_instance(francesco, studente, []), studente, []).
-
Recupera un’istanza dato il nome con cui è stata creata:
?- inst(mario, X). X = stored_instance(mario, studente, []).
-
Verifica che
studente
sia una classe.?- is_class(studente).
-
Verifica che l'oggetto passato sia un'istanza (accetta anche direttamente il nome dell'istanza):
?- inst(mario, X), is_instance(X). X = stored_instance(mario, studente, [])
?- is_instance(mario). true.
-
Verifica che l'istanza
mario
sia classe o sottoclasse dipersona
(accetta anche direttamente il nome dell'istanza)?- inst(mario, X), is_instance(X, persona). X = stored_instance(mario, studente, []).
?- is_instance(mario, persona). true.
- Per accedere ai fields di un'istanza si può utilizzare
field/3
. Ricaviamo il valore del fielduniversity
dell'istanzagiulia
.?- inst(giulia, X), field(X, university, Result). Result = 'UNIMI'
- Si può anche passare direttamente il nome di un'istanza già esistente:
?- field(giulia, university, Result). Result = 'UNIMI'
- E' possibile anche percorrere una serie di field contenenti istanze:
?- inst(giulia, X), make(pippo, studente, [container = X]). ?- inst(pippo, X), make(pippo2, studente, [container = X]). ?- inst(pippo2, X), fieldx(X, [container, container], Result). Result = stored_instance(giulia, studente, [university='UNIMI'])
-
get_method_instance/3
Utilizzato in ogni metodo creato condef_class
serve a distinguere i metodi con stesso nome e stessa arietà appartenenti a classi diverse in modo che, avendo l'istanza in input, venga richiamato il metodo corretto. Ho deciso di utilizzareasserta
nella registrazione del metodo nella base di conoscenza in modo da eseguire la ricerca depth-first partendo dalla classe "più figlia".?- inst(mario, X), get_method_instance(X, studente, talk). true.
-
superclass/2
Ottieni tutte le superclassi in modo ricorsivo partendo dal nome della classe.?- superclass(studente, X). X = studente ; X = persona.
-
verify_parts_make/2
everify_parts/2
verificano che le componenti passate siano metodi o field validi.- Nel caso di
verify_parts_make/2
viene controllato che il field esista in una delle superclassi e che abbia un tipo compatibile. Questo consente allamake
di controllare che i nuovi field assegnati esistano nella classe/superclasse e che abbiano tipo corretto. - Nel caso di
verify_parts/2
vengono fatti gli stessi controlli ma si accetta anche il caso in cui il field non è mai stato dichiarato. Questo consente alladef_class
di controllare che le superclassi non abbiano il field da ereditare o che lo ereditino col tipo corretto.
- Nel caso di
-
add_parts_make/2
eadd_parts/2
aggiungono alla base di conoscenza le componenti passate.
?- def_class(umano, [], [
field(eta, 42, float),
method(talk, [], writeln('sono umano'))
]).
true.
?- def_class(mammifero, []).
true.
?- make(capo, umano).
true.
?- inst(capo, X), def_class(persona, [umano, mammifero], [
field(nome, 'Persona', string),
field(genitore, X, umano),
method(talk, [], write('sono una persona')),
method(talk, [Input], (
field(this, eta, E),
field(this, nome, N),
write('io sono: '),
write(N),
write(' ho '),
write(E),
write(' anni.'),
write(' Ciao '),
writeln(Input))
)
]).
X = stored_instance(capo, umano, []).
?- def_class(studente, [persona], [
method(talk, [], write('sono studente')),
method(to_string, [ResultingString], (
with_output_to(string(ResultingString),
(field(this, eta, N),
field(this, nome, U),
format('#<~w Student ~w>', [U, N])
))
))
]).
true.
?- def_class(studente_bicocca, [studente], [
field(eta, 20, integer),
method(talk, [], write('studente bicocca!'))
]).
true.
?- make(scimmia, mammifero).
true.
?- make(alessandro, umano).
true.
?- inst(alessandro, X), make(francesco, persona,
[nome = "Francesco", genitore = X]).
X = stored_instance(alessandro, umano, [])
?- inst(francesco, X), make(luigi, studente, [nome = "Luigi", genitore = X]).
X = stored_instance(francesco, persona, [nome="Francesco",
genitore=stored_instance(alessandro, umano, [])]).
?- inst(luigi, X), make(collega, studente_bicocca, [genitore = X]).
X = stored_instance(luigi, studente, [nome="Luigi",
genitore=stored_instance(francesco,
persona,
[nome="Francesco", genitore=stored_instance(alessandro, umano, [])])]).
?- stored_instance(collega, X), field(X, nome, Y).
X = inst(collega, studente_bicocca, [
genitore=stored_instance(luigi, studente,
[nome="Luigi",
genitore=stored_instance(francesco, persona, [... = ...|...])])]),
Y = 'Persona'.
?- inst(luigi, X), field(X, nome, Y).
X = stored_instance(luigi, studente, [nome="Luigi",
genitore=stored_instance(francesco, persona,
[nome="Francesco", genitore=stored_instance(alessandro, umano, [])])]),
Y = "Luigi".
?- fieldx(collega, [genitore, genitore, genitore], X).
X = stored_instance(alessandro, umano, []).
?- talk(scimmia).
false.
?- talk(alessandro).
sono umano.
true.
?- inst(alessandro, X), talk(X).
sono umano.
?- inst(francesco, X), talk(X).
sono una persona.
?- inst(francesco, X), talk(X, 'Giovanni').
io sono: Francesco ho 42 anni. Ciao Giovanni
?- talk(luigi).
sono studente
true.
?- talk(collega).
studente bicocca!
true.
?- talk(collega, 'Collega').
io sono: Persona ho 20 anni. Ciao Collega
true.
?- to_string(collega, X).
X = "#<Persona Student 20>".
?- to_string(luigi, X).
X = "#<Luigi Student 42>".
%% possibilità di ridefinire istanze esistenti
?- make(alessandro, umano).
true.