Java の抽象化と契約
L'抽象化 クラスの「コントラクト」を定義できます 「何を」と「どのように」を区別し、尊重しなければなりません。 Java ではこれが実現されます と 抽象クラス e インターフェース.
何を学ぶか
- 継承と extends キーワード
- ポリモーフィズムとメソッドのオーバーライド
- 抽象クラスと抽象メソッド
- 複数のインターフェースと実装
- インターフェースのデフォルトメソッド
- 抽象クラスとインターフェイスをいつ使用するか
遺伝
L'遺伝 クラスが属性を取得できるようにします および別のクラスのメソッド。継承するクラスは次のように呼ばれます サブクラス、 それが継承するものは スーパークラス.
// Superclasse (classe padre)
public class Persona {
protected String nome;
protected String cognome;
protected int eta;
public Persona(String nome, String cognome, int eta) {
this.nome = nome;
this.cognome = cognome;
this.eta = eta;
}
public String getNomeCompleto() {
return nome + " " + cognome;
}
public void presentati() {
System.out.println("Mi chiamo " + getNomeCompleto());
}
}
// Sottoclasse (classe figlia) - eredita da Persona
public class Studente extends Persona {
private int matricola;
private double mediaVoti;
public Studente(String nome, String cognome, int eta, int matricola) {
super(nome, cognome, eta); // chiama costruttore della superclasse
this.matricola = matricola;
this.mediaVoti = 0;
}
// Metodo aggiuntivo specifico di Studente
public void studia(String materia) {
System.out.println(nome + " sta studiando " + materia);
}
// Getter
public int getMatricola() {
return matricola;
}
}
ポリモーフィズムとオーバーライド
Il 多態性 異なるクラスのオブジェクトを扱うことができます 一般的なタイプを介して。ザ」オーバーライド 再定義できます 継承されたメソッド。
public class Studente extends Persona {
private int matricola;
public Studente(String nome, String cognome, int eta, int matricola) {
super(nome, cognome, eta);
this.matricola = matricola;
}
// Override: ridefinisce il metodo della superclasse
@Override
public void presentati() {
System.out.println("Ciao! Sono " + getNomeCompleto());
System.out.println("Matricola: " + matricola);
}
}
public class Docente extends Persona {
private String materia;
public Docente(String nome, String cognome, int eta, String materia) {
super(nome, cognome, eta);
this.materia = materia;
}
@Override
public void presentati() {
System.out.println("Buongiorno, sono il Prof. " + cognome);
System.out.println("Insegno " + materia);
}
}
// Polimorfismo in azione
Persona[] persone = new Persona[3];
persone[0] = new Studente("Mario", "Rossi", 20, 123456);
persone[1] = new Docente("Luigi", "Verdi", 45, "Programmazione");
persone[2] = new Persona("Anna", "Bianchi", 30);
for (Persona p : persone) {
p.presentati(); // chiama il metodo corretto per ogni tipo
System.out.println("---");
}
オーバーライドルール
- 注釈
@Overrideオプションですが推奨されます - メソッドには同じシグネチャ (名前とパラメータ) が必要です。
- 戻り値の型は同じかサブタイプである必要があります
- 可視性を下げることはできません(パブリックからプライベートに)
- メソッドをオーバーライドすることはできません
finalostatic
抽象クラス
Una 抽象クラス 直接インスタンス化することはできません サブクラス化する抽象 (実装不要) メソッドを含めることができます。 彼らは実装しなければなりません。
// Classe astratta: non può essere istanziata
public abstract class FormaGeometrica {
protected String nome;
protected String colore;
public FormaGeometrica(String nome, String colore) {
this.nome = nome;
this.colore = colore;
}
// Metodo concreto: ha implementazione
public void descrivi() {
System.out.println("Sono un/una " + nome + " di colore " + colore);
}
// Metodi astratti: senza implementazione, le sottoclassi DEVONO implementarli
public abstract double calcolaArea();
public abstract double calcolaPerimetro();
}
// Sottoclasse concreta: DEVE implementare tutti i metodi astratti
public class Cerchio extends FormaGeometrica {
private double raggio;
public Cerchio(String colore, double raggio) {
super("cerchio", colore);
this.raggio = raggio;
}
@Override
public double calcolaArea() {
return Math.PI * raggio * raggio;
}
@Override
public double calcolaPerimetro() {
return 2 * Math.PI * raggio;
}
}
public class Rettangolo extends FormaGeometrica {
private double base;
private double altezza;
public Rettangolo(String colore, double base, double altezza) {
super("rettangolo", colore);
this.base = base;
this.altezza = altezza;
}
@Override
public double calcolaArea() {
return base * altezza;
}
@Override
public double calcolaPerimetro() {
return 2 * (base + altezza);
}
}
// Utilizzo
FormaGeometrica[] forme = {
new Cerchio("rosso", 5),
new Rettangolo("blu", 4, 3)
};
for (FormaGeometrica forma : forme) {
forma.descrivi();
System.out.printf("Area: %.2f, Perimetro: %.2f%n",
forma.calcolaArea(), forma.calcolaPerimetro());
}
インターフェース
あ'インタフェース コントラクトを定義します: メソッドのセット 実装クラスが提供する必要があります。抽象クラスとは異なり、 クラスは実装できる 複数のインターフェース.
// Interfaccia: definisce un contratto
public interface Valutabile {
// Tutti i metodi sono implicitamente public abstract
double getVoto();
String getGiudizio();
}
public interface Stampabile {
void stampa();
}
public interface Esportabile {
String esportaJSON();
String esportaCSV();
}
// Una classe può implementare MULTIPLE interfacce
public class Esame implements Valutabile, Stampabile, Esportabile {
private String nomeCorso;
private int voto;
private boolean lode;
public Esame(String nomeCorso, int voto, boolean lode) {
this.nomeCorso = nomeCorso;
this.voto = voto;
this.lode = lode && voto == 30;
}
// Implementazione Valutabile
@Override
public double getVoto() {
return voto;
}
@Override
public String getGiudizio() {
if (voto >= 28) return "Ottimo";
if (voto >= 24) return "Buono";
if (voto >= 18) return "Sufficiente";
return "Insufficiente";
}
// Implementazione Stampabile
@Override
public void stampa() {
String votoStr = lode ? "30 e Lode" : String.valueOf(voto);
System.out.println(nomeCorso + ": " + votoStr + " (" + getGiudizio() + ")");
}
// Implementazione Esportabile
@Override
public String esportaJSON() {
return String.format("{\"corso\":\"%s\",\"voto\":%d,\"lode\":%b}",
nomeCorso, voto, lode);
}
@Override
public String esportaCSV() {
return String.format("%s,%d,%b", nomeCorso, voto, lode);
}
}
デフォルトのメソッド (Java 8 以降)
public interface Calcolabile {
double calcola();
// Default method: ha un'implementazione di default
default String formattaRisultato() {
return String.format("%.2f", calcola());
}
// Static method nell'interfaccia
static double arrotonda(double valore, int decimali) {
double fattore = Math.pow(10, decimali);
return Math.round(valore * fattore) / fattore;
}
}
public class MediaVoti implements Calcolabile {
private int[] voti;
public MediaVoti(int... voti) {
this.voti = voti;
}
@Override
public double calcola() {
int somma = 0;
for (int v : voti) somma += v;
return (double) somma / voti.length;
}
// Può override il default method se vuole
@Override
public String formattaRisultato() {
return "Media: " + String.format("%.2f", calcola()) + "/30";
}
}
抽象クラスとインターフェイスの比較
比較
| 待ってます | 抽象クラス | インタフェース |
|---|---|---|
| 遺伝 | シングル(延長) | 複数(実装) |
| ビルダー | Si | No |
| ステータス(属性) | はい(どれでも) | 定数のみ (静的最終) |
| 具体的な方法 | Si | デフォルト/静的のみ |
| 一般的な使用方法 | 国家との共通基盤 | 行動契約 |
いつ何を使うか
- 抽象クラス: 共有する共通のコード、ステータス、または関係「およびそのタイプ」がある場合
- インタフェース: さまざまなクラスが実装できる動作を定義したい場合
- 両方: インターフェースを実装した抽象クラスを使用できます
完全な例: 大学システム
public interface Valutabile {
double getMedia();
String getGiudizio();
}
public interface Identificabile {
String getCodice();
String getTipo();
}
public abstract class MembroUniversita implements Identificabile {
protected String nome;
protected String cognome;
protected String codice;
public MembroUniversita(String nome, String cognome, String codice) {
this.nome = nome;
this.cognome = cognome;
this.codice = codice;
}
public String getNomeCompleto() {
return nome + " " + cognome;
}
@Override
public String getCodice() {
return codice;
}
// Metodo astratto: ogni sottoclasse definisce il suo comportamento
public abstract void svolgiFunzione();
}
public class StudenteUniversitario extends MembroUniversita implements Valutabile {
private int[] voti = new int[20];
private int numEsami = 0;
public StudenteUniversitario(String nome, String cognome, int matricola) {
super(nome, cognome, "S" + matricola);
}
public void registraEsame(int voto) {
if (numEsami < voti.length && voto >= 18 && voto <= 30) {
voti[numEsami++] = voto;
}
}
@Override
public String getTipo() {
return "Studente";
}
@Override
public void svolgiFunzione() {
System.out.println(getNomeCompleto() + " studia per gli esami");
}
@Override
public double getMedia() {
if (numEsami == 0) return 0;
int somma = 0;
for (int i = 0; i < numEsami; i++) somma += voti[i];
return (double) somma / numEsami;
}
@Override
public String getGiudizio() {
double media = getMedia();
if (media >= 28) return "Eccellente";
if (media >= 24) return "Buono";
if (media >= 18) return "Sufficiente";
return "In corso";
}
}
public class Professore extends MembroUniversita {
private String materia;
private int oreSettimanali;
public Professore(String nome, String cognome, String codice, String materia) {
super(nome, cognome, "P" + codice);
this.materia = materia;
this.oreSettimanali = 20;
}
@Override
public String getTipo() {
return "Professore";
}
@Override
public void svolgiFunzione() {
System.out.println("Prof. " + cognome + " insegna " + materia);
}
public void assegnaVoto(StudenteUniversitario studente, int voto) {
studente.registraEsame(voto);
System.out.printf("Il Prof. %s ha assegnato %d a %s%n",
cognome, voto, studente.getNomeCompleto());
}
}
public class TestUniversita {
public static void main(String[] args) {
// Creazione membri
StudenteUniversitario mario = new StudenteUniversitario("Mario", "Rossi", 123456);
StudenteUniversitario anna = new StudenteUniversitario("Anna", "Bianchi", 789012);
Professore profVerdi = new Professore("Luigi", "Verdi", "001", "Programmazione");
// Assegnazione voti
profVerdi.assegnaVoto(mario, 28);
profVerdi.assegnaVoto(mario, 30);
profVerdi.assegnaVoto(anna, 24);
profVerdi.assegnaVoto(anna, 26);
// Polimorfismo: array di tipo base
MembroUniversita[] membri = {mario, anna, profVerdi};
System.out.println("\n=== Membri Universita ===");
for (MembroUniversita m : membri) {
System.out.println(m.getTipo() + ": " + m.getNomeCompleto());
System.out.println("Codice: " + m.getCodice());
m.svolgiFunzione();
// Verifica se implementa Valutabile
if (m instanceof Valutabile) {
Valutabile v = (Valutabile) m;
System.out.printf("Media: %.2f - %s%n", v.getMedia(), v.getGiudizio());
}
System.out.println("---");
}
}
}
結論
この記事では、継承、ポリモーフィズム、抽象クラスについて説明しました。 およびインターフェイス - コードの作成を可能にする OOP の高度な柱 柔軟で再利用可能。
Nel 次の記事 見てみましょう JavaコアAPI: String、StringBuilder、Wrapper クラスおよび日付/時刻 API。
覚えておくべき重要なポイント
- 延長します: クラスからの単一継承
- 実装: インターフェース実装(複数)
- @オーバーライド: スーパークラスのメソッドをオーバーライドします
- 抽象的な: 実装のないメソッド、インスタンス化できないクラス
- インタフェース: ステートレスな行動契約
- デフォルト: インターフェースに実装されたメソッド







