Mini App Gestione Prodotti Android: OOP Completa in Java

Mini app Android “Gestione Prodotti” in Java: guida completa all’OOP (incapsulamento, ereditarietà, polimorfismo, astrazione)

In questo tutorial creeremo una mini app Android in Java chiamata Gestione Prodotti, pensata per mettere in pratica in modo concreto tutti e quattro i principi fondamentali della programmazione orientata agli oggetti (OOP): incapsulamento, ereditarietà, polimorfismo e astrazione.

Mini App Gestione Prodotti Android OOP Java

L’app mostrerà una lista di prodotti in una RecyclerView, permetterà di aggiungere nuovi prodotti tramite un pulsante FloatingActionButton (FAB) e mostrerà i dettagli del prodotto in un AlertDialog quando l’utente tocca un elemento della lista. Niente database, niente API: solo Java OOP + componenti standard Android.

Obiettivo didattico della mini app gestione prodotti

L’obiettivo è vedere come i concetti OOP si traducono in codice reale Android:

  • Incapsulamento: nascondiamo i dati interni della classe Prodotto usando campi privati e metodi getter/setter.
  • Ereditarietà: usiamo Prodotto come classe base astratta e creiamo ProdottoFisico e ProdottoDigitale come sottoclassi.
  • Polimorfismo: definiamo un metodo calcolaPrezzo() che si comporta in modo diverso in base al tipo di prodotto.
  • Astrazione: definiamo l’interfaccia Vendibile che rappresenta il concetto astratto di “cosa può essere venduta”.

Struttura della mini app gestione prodotti Android

  • Schermata principale: MainActivity con RecyclerView che mostra nome, tipo e prezzo calcolato.
  • Pulsante FAB: apre un Dialog per aggiungere un nuovo prodotto (nome, tipo, prezzo base).
  • Tap su un prodotto: mostra un AlertDialog con dettagli (tipo, prezzo calcolato, descrizione).
  • Nessun database: usiamo solo una lista in memoria.

1. Preparazione del progetto Android per la mini app gestione prodotti

Per seguire il tutorial ti serve Android Studio aggiornato.

  • Crea un nuovo progetto Empty Activity.
  • Linguaggio: Java.
  • Minimum SDK: per esempio API 21 (Android 5.0) o superiore.

Assicurati che nel file build.gradle (Module: app) sia presente la dipendenza per RecyclerView (di solito è già inclusa nei template moderni):

dependencies {
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
}

2. Astrazione: interfaccia Vendibile

Partiamo dall’astrazione. Vogliamo rappresentare il concetto generale di qualcosa che può essere venduta. A questo livello non ci importa se sia un prodotto fisico o digitale: ci interessano solo le operazioni comuni.

Creiamo un’interfaccia Vendibile con due metodi:

  • double calcolaPrezzo(): ritorna il prezzo finale per l’utente.
  • String getDescrizione(): ritorna una descrizione leggibile del prodotto.

Questa interfaccia incarna il principio di astrazione: definiamo che cosa può fare un oggetto vendibile, senza preoccuparci di come lo farà.

Codice: Vendibile.java

package com.example.gestioneprodotti.oop;

/**
 * Interfaccia che rappresenta qualcosa che può essere venduta.
 * Qui applichiamo il principio di ASTRAZIONE:
 * - definiamo solo le operazioni comuni (cosa può fare)
 * - non conosciamo ancora i dettagli concreti (come lo farà)
 */
public interface Vendibile {

    /**
     * Calcola il prezzo finale da far pagare al cliente.
     */
    double calcolaPrezzo();

    /**
     * Ritorna una descrizione testuale del prodotto.
     */
    String getDescrizione();
}

3. Incapsulamento + astrazione: classe astratta Prodotto (app gestione prodotti)

Ora creiamo la classe base Prodotto, che rappresenta ciò che hanno in comune tutti i prodotti (fisici o digitali). Qui combiniamo due principi:

  • Incapsulamento: i dati (nome, prezzo base, tipo, quantita) sono privati e accessibili solo tramite getter/setter.
  • Astrazione: rendiamo la classe astratta e facciamo implementare l’interfaccia Vendibile, delegando i dettagli alle sottoclassi.

Crea il file Prodotto.java nel package com.example.gestioneprodotti.oop:

package com.example.gestioneprodotti.oop;

/**
 * Classe base astratta che rappresenta un prodotto generico.
 *
 * - Implementa l'interfaccia Vendibile (ASTRAZIONE)
 * - Usa campi privati e getter/setter (INCAPSULAMENTO)
 */
public abstract class Prodotto implements Vendibile {

    // INCAPSULAMENTO: i campi sono privati
    private String nome;
    private double prezzoBase;
    private String tipo;
    private int quantita;

    public Prodotto(String nome, double prezzoBase, String tipo, int quantita) {
        this.nome = nome;
        this.prezzoBase = prezzoBase;
        this.tipo = tipo;
        this.quantita = quantita;
    }

    // Getter e setter incapsulano l'accesso ai dati interni
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public double getPrezzoBase() {
        return prezzoBase;
    }

    public void setPrezzoBase(double prezzoBase) {
        this.prezzoBase = prezzoBase;
    }

    public String getTipo() {
        return tipo;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    public int getQuantita() {
        return quantita;
    }

    public void setQuantita(int quantita) {
        if (quantita >= 0) this.quantita = quantita;
    }

    @Override
    public String toString() {
        return nome + " (" + tipo + ")";
    }
}

Nota: non implementiamo qui il metodo calcolaPrezzo() dell’interfaccia Vendibile. Lo lasceremo alle sottoclassi, che applicheranno il polimorfismo calcolando il prezzo in modo diverso.

4. Ereditarietà + polimorfismo: ProdottoFisico e ProdottoDigitale (mini app gestione prodotti)

Ora applichiamo l’ereditarietà: creiamo due sottoclassi che estendono Prodotto e implementano i metodi dell’interfaccia Vendibile in modo diverso (qui entra in gioco il polimorfismo).

ProdottoFisico: aggiunge le spese di spedizione

Per i prodotti fisici vogliamo aggiungere un costo fisso di spedizione, ad esempio €4,99. Quindi:

  • calcolaPrezzo() = prezzoBase + 4.99
  • getDescrizione() indica che si tratta di un prodotto fisico con spedizione.
package com.example.gestioneprodotti.oop;

/**
 * Sottoclasse che rappresenta un prodotto fisico.
 *
 * - EREDITA da Prodotto (EREDITARIETÀ)
 * - Implementa calcolaPrezzo() in modo specifico (POLIMORFISMO)
 */
public class ProdottoFisico extends Prodotto {

    private static final double COSTO_SPEDIZIONE = 4.99;

    public ProdottoFisico(String nome, double prezzoBase, int quantita) {
        // Passiamo "Fisico" come tipo alla superclasse
        super(nome, prezzoBase, "Fisico", quantita);
    }

    @Override
    public double calcolaPrezzo() {
        // POLIMORFISMO: per il prodotto fisico aggiungiamo le spese di spedizione
        return getPrezzoBase() + COSTO_SPEDIZIONE;
    }

    @Override
    public String getDescrizione() {
        return "Prodotto fisico: " + getNome() +
                "\nPrezzo base: " + String.format("%.2f", getPrezzoBase()) + " €" +
                "\nSpedizione: " + String.format("%.2f", COSTO_SPEDIZIONE) + " €" +
                "\nPrezzo finale: " + String.format("%.2f", calcolaPrezzo()) + " €";
    }
}

ProdottoDigitale: applica una riduzione del 10% (IVA digitale)

Per i prodotti digitali vogliamo simulare una riduzione del 10%, ad esempio per IVA agevolata. Quindi:

  • calcolaPrezzo() = prezzoBase * 0.90
  • getDescrizione() indica che si tratta di un prodotto digitale con sconto.
package com.example.gestioneprodotti.oop;

/**
 * Sottoclasse che rappresenta un prodotto digitale.
 *
 * - EREDITA da Prodotto (EREDITARIETÀ)
 * - Implementa calcolaPrezzo() in modo specifico (POLIMORFISMO)
 */
public class ProdottoDigitale extends Prodotto {

    private static final double SCONTO_DIGITALE = 0.10; // 10%

    public ProdottoDigitale(String nome, double prezzoBase, int quantita) {
        // Passiamo "Digitale" come tipo alla superclasse
        super(nome, prezzoBase, "Digitale", quantita);
    }

    @Override
    public double calcolaPrezzo() {
        // POLIMORFISMO: per il prodotto digitale applichiamo uno sconto del 10%
        return getPrezzoBase() * (1 - SCONTO_DIGITALE);
    }

    @Override
    public String getDescrizione() {
        return "Prodotto digitale: " + getNome() +
                "\nPrezzo base: " + String.format("%.2f", getPrezzoBase()) + " €" +
                "\nSconto digitale: " + (int) (SCONTO_DIGITALE * 100) + "%" +
                "\nPrezzo finale: " + String.format("%.2f", calcolaPrezzo()) + " €";
    }
}

Ora abbiamo due classi concrete che possono essere trattate in modo generico come Vendibile o Prodotto, ma che si comportano in modo diverso quando chiamiamo calcolaPrezzo(). Questo è polimorfismo in azione.

5. Layout XML: activity_main, item_prodotto e dialog_aggiungi_prodotto

Prima di passare alla logica Java dell’interfaccia utente, creiamo i layout XML che useremo nella mini app.

5.1 activity_main.xml: RecyclerView + FAB

Il layout principale usa un CoordinatorLayout e contiene una RecyclerView a schermo intero e un FloatingActionButton per aggiungere nuovi prodotti.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewProdotti"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        tools:listitem="@layout/item_prodotto" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabAggiungiProdotto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="Aggiungi prodotto"
        app:srcCompat="@android:drawable/ic_input_add"
        app:layout_anchor="@id/recyclerViewProdotti"
        app:layout_anchorGravity="bottom|end"
        android:layout_margin="16dp" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

5.2 item_prodotto.xml: layout per ogni elemento della lista

Ogni elemento della RecyclerView mostrerà:

  • Nome del prodotto
  • Tipo (Fisico/Digitale)
  • Prezzo calcolato (usando il polimorfismo)
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    card_view:cardElevation="2dp"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="12dp">

        <TextView
            android:id="@+id/textNomeProdotto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textSize="16sp"
            android:text="Nome prodotto" />

        <TextView
            android:id="@+id/textTipoProdotto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Tipo" />

        <TextView
            android:id="@+id/textPrezzoProdotto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="0,00 €" />

        <TextView
            android:id="@+id/textQuantitaProdotto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Qtà: 0" />

    </LinearLayout>

</androidx.cardview.widget.CardView>

5.3 dialog_aggiungi_prodotto.xml: dialog per aggiungere un prodotto

Infine, creiamo un layout per il Dialog che permetterà all’utente di inserire:

  • Nome del prodotto (EditText)
  • Prezzo base (EditText numerico)
  • Tipo (RadioGroup con due RadioButton: Fisico, Digitale)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/editNomeProdotto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Nome prodotto"
        android:inputType="textPersonName" />

    <EditText
        android:id="@+id/editPrezzoBase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Prezzo base (€)"
        android:inputType="numberDecimal"
        android:layout_marginTop="8dp" />

    <EditText
        android:id="@+id/editQuantita"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Quantità"
        android:inputType="number"
        android:layout_marginTop="8dp" />

    <RadioGroup
        android:id="@+id/radioGroupTipo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="8dp">

        <RadioButton
            android:id="@+id/radioFisico"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Fisico" />

        <RadioButton
            android:id="@+id/radioDigitale"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Digitale"
            android:layout_marginStart="16dp" />

    </RadioGroup>

</LinearLayout>

6. RecyclerView e polimorfismo: ProdottoAdapter (gestione prodotti Android)

Ora creiamo l’adapter per la RecyclerView. Questa classe non introduce nuovi concetti OOP, ma usa il polimorfismo delle nostre classi prodotto: per ogni elemento chiamiamo semplicemente calcolaPrezzo() sul riferimento Prodotto senza preoccuparci se sia fisico o digitale.

Crea il file ProdottoAdapter.java nel package principale (com.example.gestioneprodotti):

package com.example.gestioneprodotti;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.gestioneprodotti.oop.Prodotto;

import java.util.List;

/**
 * Adapter per la RecyclerView che mostra la lista di prodotti.
 * Usa il POLIMORFISMO chiamando calcolaPrezzo() su Prodotto,
 * senza conoscere il tipo concreto (fisico o digitale).
 */
public class ProdottoAdapter extends RecyclerView.Adapter<ProdottoAdapter.ProdottoViewHolder> {

    public interface OnItemClickListener {
        void onItemClick(Prodotto prodotto);
    }

    private List<Prodotto> prodotti;
    private OnItemClickListener listener;

    public ProdottoAdapter(List<Prodotto> prodotti, OnItemClickListener listener) {
        this.prodotti = prodotti;
        this.listener = listener;
    }

    @NonNull
    @Override
    public ProdottoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_prodotto, parent, false);
        return new ProdottoViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ProdottoViewHolder holder, int position) {
        final Prodotto prodotto = prodotti.get(position);
        holder.bind(prodotto, listener);
    }

    @Override
    public int getItemCount() {
        return prodotti.size();
    }

    static class ProdottoViewHolder extends RecyclerView.ViewHolder {

        TextView textNome;
        TextView textTipo;
        TextView textPrezzo;
        TextView textQuantita;

        public ProdottoViewHolder(@NonNull View itemView) {
            super(itemView);
            textNome = itemView.findViewById(R.id.textNomeProdotto);
            textTipo = itemView.findViewById(R.id.textTipoProdotto);
            textPrezzo = itemView.findViewById(R.id.textPrezzoProdotto);
            textQuantita = itemView.findViewById(R.id.textQuantitaProdotto);
        }

        public void bind(final Prodotto prodotto, final OnItemClickListener listener) {
            textNome.setText(prodotto.getNome());
            textTipo.setText(prodotto.getTipo());

            // POLIMORFISMO: il prezzo è calcolato in modo diverso
            // a seconda del tipo concreto di Prodotto
            double prezzoFinale = prodotto.calcolaPrezzo();
            textPrezzo.setText(String.format("%.2f €", prezzoFinale));
            textQuantita.setText("Qtà: " + prodotto.getQuantita());

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        listener.onItemClick(prodotto);
                    }
                }
            });
        }
    }
}

7. MainActivity: gestione lista, FAB e dialog

MainActivity mette insieme tutti i pezzi:

  • Inizializza la RecyclerView e l’adapter.
  • Crea una lista in memoria di Prodotto (sia fisici che digitali).
  • Gestisce il click sul FAB per aprire il Dialog di aggiunta.
  • Gestisce il tap su un elemento per mostrare un AlertDialog con i dettagli (usando getDescrizione()).

Codice: MainActivity.java

package com.example.gestioneprodotti;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.gestioneprodotti.oop.Prodotto;
import com.example.gestioneprodotti.oop.ProdottoDigitale;
import com.example.gestioneprodotti.oop.ProdottoFisico;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;

/**
 * Activity principale dell'app "Gestione Prodotti".
 * Qui utilizziamo le nostre classi OOP per popolare la UI.
 */
public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ProdottoAdapter adapter;
    private List<Prodotto> listaProdotti;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = findViewById(R.id.recyclerViewProdotti);
        FloatingActionButton fab = findViewById(R.id.fabAggiungiProdotto);

        // Inizializziamo la lista con qualche prodotto di esempio
        listaProdotti = new ArrayList<>();
        listaProdotti.add(new ProdottoFisico("Libro Java", 29.90, 10));
        listaProdotti.add(new ProdottoDigitale("Corso Android Online", 99.00, 5));
        listaProdotti.add(new ProdottoFisico("Mouse wireless", 15.50, 3));

        adapter = new ProdottoAdapter(listaProdotti, new ProdottoAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(Prodotto prodotto) {
                mostraDettagliProdotto(prodotto);
            }
        });

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mostraDialogAggiungiProdotto();
            }
        });
    }

    private void mostraDettagliProdotto(Prodotto prodotto) {
        // Usiamo il metodo getDescrizione() definito nell'interfaccia Vendibile
        new AlertDialog.Builder(this)
                .setTitle(prodotto.getNome())
                .setMessage(prodotto.getDescrizione())
                .setPositiveButton("OK", null)
                .show();
    }

    private void mostraDialogAggiungiProdotto() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Aggiungi prodotto");

        LayoutInflater inflater = getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_aggiungi_prodotto, null);
        builder.setView(dialogView);

        EditText editNome = dialogView.findViewById(R.id.editNomeProdotto);
        EditText editPrezzo = dialogView.findViewById(R.id.editPrezzoBase);
        EditText editQuantita = dialogView.findViewById(R.id.editQuantita);
        RadioGroup radioGroupTipo = dialogView.findViewById(R.id.radioGroupTipo);
        RadioButton radioFisico = dialogView.findViewById(R.id.radioFisico);
        RadioButton radioDigitale = dialogView.findViewById(R.id.radioDigitale);

        // Impostiamo di default "Fisico"
        radioFisico.setChecked(true);

        builder.setPositiveButton("Aggiungi", null);
        builder.setNegativeButton("Annulla", null);

        AlertDialog dialog = builder.create();
        dialog.show();

        // Sovrascriviamo il click del pulsante "Aggiungi" per poter validare i dati
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String nome = editNome.getText().toString().trim();
                String prezzoStr = editPrezzo.getText().toString().trim();
                String quantitaStr = editQuantita.getText().toString().trim();

                if (TextUtils.isEmpty(nome)) {
                    editNome.setError("Inserisci un nome");
                    return;
                }

                if (TextUtils.isEmpty(prezzoStr)) {
                    editPrezzo.setError("Inserisci un prezzo");
                    return;
                }

                if (TextUtils.isEmpty(quantitaStr)) {
                    editQuantita.setError("Inserisci una quantità");
                    return;
                }

                double prezzoBase;
                try {
                    prezzoBase = Double.parseDouble(prezzoStr.replace(",", "."));
                } catch (NumberFormatException e) {
                    editPrezzo.setError("Prezzo non valido");
                    return;
                }

                int quantita;
                try {
                    quantita = Integer.parseInt(quantitaStr);
                } catch (NumberFormatException e) {
                    editQuantita.setError("Quantità non valida");
                    return;
                }

                int selectedId = radioGroupTipo.getCheckedRadioButtonId();
                Prodotto nuovoProdotto;

                if (selectedId == R.id.radioDigitale) {
                    nuovoProdotto = new ProdottoDigitale(nome, prezzoBase, quantita);
                } else {
                    nuovoProdotto = new ProdottoFisico(nome, prezzoBase, quantita);
                }

                // Aggiungiamo il nuovo prodotto alla lista e notifichiamo l'adapter
                listaProdotti.add(nuovoProdotto);
                adapter.notifyItemInserted(listaProdotti.size() - 1);
                recyclerView.scrollToPosition(listaProdotti.size() - 1);

                dialog.dismiss();
            }
        });
    }
}

8. Come i 4 principi OOP lavorano insieme nella mini app gestione prodotti

Ricapitoliamo come abbiamo applicato in pratica i quattro pilastri dell’OOP in questa mini app Gestione Prodotti:

  • Incapsulamento: la classe Prodotto nasconde i suoi dati interni (nome, prezzoBase, tipo, quantita) usando campi privati e fornendo solo getter/setter. In questo modo il resto dell’app non accede mai direttamente ai campi, ma passa da metodi controllati. Il campo quantita, ad esempio, è aggiornato tramite un setter che valida l’input (if (quantita >= 0)).
  • Ereditarietà: ProdottoFisico e ProdottoDigitale estendono Prodotto, riutilizzando tutto ciò che è comune (nome, prezzo base, tipo) e aggiungendo il proprio comportamento specifico per il calcolo del prezzo e la descrizione.
  • Polimorfismo: sia l’adapter della RecyclerView sia la MainActivity lavorano con riferimenti di tipo Prodotto o Vendibile. Quando chiamano calcolaPrezzo() o getDescrizione(), viene eseguita automaticamente l’implementazione corretta in base al tipo concreto (fisico o digitale), senza dover scrivere if/switch espliciti.
  • Astrazione: l’interfaccia Vendibile e la classe astratta Prodotto rappresentano il concetto generale di “qualcosa che può essere venduta”, indipendentemente dai dettagli. In futuro potremmo aggiungere altri tipi di prodotti (es. ServizioInAbbonamento) semplicemente implementando l’interfaccia e, se serve, estendendo Prodotto.

Questa architettura rende il codice più leggibile, più estendibile e più facile da manutenere. Puoi usare la stessa struttura per altri mini progetti Android in Java (gestione ordini, gestione utenti, ecc.), sostituendo i “prodotti” con le entità del tuo dominio.

Se vuoi fare un passo oltre, puoi provare a:

  • Aggiungere un nuovo tipo di prodotto (es. “Servizio”) con una sua logica di prezzo.
  • Mostrare più campi nella lista (es. data di creazione, quantità).
  • Persistere i prodotti con Room o SharedPreferences mantenendo invariata la gerarchia OOP.

In questo modo consoliderai ancora di più la comprensione dei principi OOP applicati allo sviluppo Android in Java.

Commenti

Rispondi

Scopri di più da App Tutorial

Abbonati ora per continuare a leggere e avere accesso all'archivio completo.

Continua a leggere