classe in lingua OOP e tipo

9

Nella teoria del linguaggio di programmazione, un tipo è un insieme di valori. Per esempio. il tipo "int" è l'insieme di tutti i valori interi.

Nei linguaggi OOP, una classe è un tipo, vero?

Quando una classe è definita con più di un membro, ad es.

class myclass{
    int a; 
    double b;
}

Quando parliamo di una classe, intendiamo

  • " (a,b) dove a è un int e b è un doppio", o
  • "{ (x,y) | x è qualsiasi int, y è qualsiasi doppio}"?

Che cosa significa un'istanza di myclass ?

  • " (a,b) dove a è un int e b è un doppio", o
  • un oggetto che occupa uno spazio di memoria e che può (non necessariamente, cioè può essere vuoto) memorizzare (x,y) , dove x è qualsiasi int e y è un qualsiasi doppio?
posta Tim 21.01.2015 - 15:05
fonte

5 risposte

30

Nessuno dei due.

Suppongo che tu stia chiedendo se avere lo stesso set di tipi di campi sia sufficiente per classificarli come appartenenti alla stessa classe, o se debbano essere nominati identicamente. La risposta è: "Non abbiamo nemmeno gli stessi tipi e gli stessi nomi sono sufficienti!" Le classi equivalenti strutturalmente non sono necessariamente compatibili con i tipi.

Ad esempio, se hai una CartesianCoordinates e una PolarCordinates class, potrebbero avere entrambi due numeri come campi, e potrebbero anche avere lo stesso Number type e gli stessi nomi, ma sarebbero comunque non essere compatibile e un'istanza di PolarCoordinates non sarebbe un'istanza di CartesianCoordinates . La possibilità di separare i tipi in base al loro scopo e non alla loro attuale implementazione è una parte molto utile della scrittura di codice più sicuro e più gestibile.

    
risposta data 21.01.2015 - 15:11
fonte
6

I tipi non sono set.

Come vedi, la teoria degli insiemi ha un numero di caratteristiche che semplicemente non si applicano ai tipi, e vice-versa . Ad esempio, un oggetto ha un singolo tipo canonico. Può essere un'istanza di diversi tipi, ma solo uno di questi tipi è stato utilizzato per istanziarlo. La teoria degli insiemi non ha la nozione di insiemi "canonici".

La teoria degli insiemi ti consente di creare sottoinsiemi al volo , se hai una regola che descrive ciò che appartiene al sottoinsieme . La teoria dei tipi in genere non lo consente. Mentre molte lingue hanno un tipo Number o qualcosa di simile, non hanno un tipo EvenNumber , né sarebbe semplice crearne uno. Voglio dire, è abbastanza facile definire il tipo stesso, ma qualsiasi Number s esistente che capita di essere anche non sarà magicamente trasformato in EvenNumber s.

In realtà, dire che è possibile "creare" sottoinsiemi è in qualche modo disonesto, perché gli insiemi sono un tipo di animale completamente diverso. Nella teoria degli insiemi, quei sottoinsiemi esistono già , in tutti i modi infiniti in cui è possibile definirli. Nella teoria dei tipi, di solito ci si aspetta di avere a che fare con un numero finito (se grande) di tipi in un dato momento. Gli unici tipi che si dice esistano sono quelli che abbiamo effettivamente definito, non tutti i tipi che potremmo definire.

Gli insiemi sono non autorizzati a contenere se stessi direttamente o indirettamente . Alcuni linguaggi, come Python, forniscono tipi con strutture meno regolari (in Python, il tipo canonico di type è type e object è considerato un'istanza di object ). D'altra parte, la maggior parte delle lingue non consente tipi definiti dall'utente per ingannare questo tipo di inganno.

È comunemente permesso che gli insiemi si sovrappongano senza essere contenuti l'uno nell'altro. Questo è raro nella teoria dei tipi, sebbene alcuni linguaggi lo supportino sotto forma di ereditarietà multipla. Altri linguaggi, come Java, consentono solo una forma limitata di questo o non lo consentono completamente.

Il tipo vuoto esiste (si chiama tipo di fondo ), ma la maggior parte delle lingue non lo supporta, o no considerarlo come un tipo di prima classe. Esiste anche il "tipo che contiene tutti gli altri tipi" (si chiama top type ) ed è ampiamente supportato, a differenza della teoria degli insiemi .

NB : come alcuni commentatori hanno precedentemente indicato (prima che il thread fosse spostato in chat), è possibile modellare i tipi con la teoria degli insiemi e altri costrutti matematici standard. Ad esempio, è possibile modellare l'appartenenza al tipo come relazione piuttosto che i tipi di modelli come insiemi. Ma in pratica, questo è molto più semplice se usi la teoria delle categorie invece della teoria degli insiemi. Questo è il modo in cui Haskell modella la sua teoria del tipo, per esempio.

La nozione di "sottotipizzazione" è in realtà molto diversa dalla nozione di "sottoinsieme". Se X è un sottotipo di Y , significa che possiamo sostituire istanze di Y per istanze di X e il programma continuerà a "funzionare" in un certo senso. Questo è comportamentale piuttosto che strutturale, anche se alcuni linguaggi (ad esempio Go, Rust, probabilmente C) hanno scelto quest'ultimo per ragioni di convenienza, sia per il programmatore che per l'implementazione del linguaggio.

    
risposta data 21.01.2015 - 21:24
fonte
4

I tipi di dati algebrici sono il modo per discuterne.

Esistono tre modi fondamentali per combinare i tipi:

  • del prodotto. Questo è fondamentalmente ciò a cui stai pensando:

    struct IntXDouble{
      int a; 
      double b;
    }
    

    è un tipo di prodotto; i suoi valori sono tutte le combinazioni possibili (cioè tuple) di un int e un double . Se consideri i tipi di numero come insiemi, la cardinalità del tipo di prodotto è in realtà il prodotto delle cardinalità dei campi.

  • Somma. Nei linguaggi procedurali questo è un po 'difficile da esprimere direttamente (in genere è fatto con unioni tag ), quindi per una migliore comprensione, ecco un tipo di somma in Haskell:

    data IntOrDouble = AnInt Int
                     | ADouble Double
    

    i valori di questo tipo hanno la forma AnInt 345 o ADouble 4.23 , ma è sempre presente un solo numero (a differenza del tipo di prodotto, in cui ogni valore ha due numeri). Quindi la cardinalità: per prima cosa enumerate tutti i valori di Int , ognuno deve essere combinato con il costruttore di AnInt . Più , tutti i valori di Double , ciascuno combinato con ADouble . Quindi tipo di somma .

  • Esponenziazione 1 . Non discuterò in dettaglio qui perché non ha alcuna corrispondenza OO chiara.

Quindi per quanto riguarda le classi? Ho utilizzato deliberatamente la parola chiave struct anziché class per IntXDouble . Il fatto è che una classe come tipo non è realmente caratterizzata dai suoi campi, questi sono solo dettagli di implementazione. Il fattore cruciale è piuttosto, quali valori distinguibili possono avere la classe.

Ciò che è rilevante è, il valore di una classe può essere valori di qualsiasi delle sue sottoclassi ! Quindi una classe è in realtà un tipo di somma piuttosto che un tipo di prodotto: se A e B sarebbero entrambi derivati da myClass , il myClass sarebbe essenzialmente la somma di A e B . Indipendentemente dall'attuazione effettiva.

1 Questa è una funzione (nel senso matematico! ); un tipo di funzione Int -> Double è rappresentato dall'esponenziale Double Int . A male se la tua lingua non ha funzioni appropriate ...

    
risposta data 22.01.2015 - 03:08
fonte
2

Scusa ma non conosco la teoria "grezza". Posso solo fornire un approccio pratico. Spero che sia accettabile su programmers.SE; Non ho familiarità con l'etichetta qui.

Un tema centrale di OOP è nascondere le informazioni . Ciò che i dati membri di una classe sono, esattamente, non dovrebbero essere di alcun interesse per i suoi clienti. Un client invia messaggi a (chiama metodi / funzioni membro di) un'istanza, che potrebbe o potrebbe non modificare lo stato interno. L'idea è che le parti interne di una classe possano cambiare, senza che il client ne risenta.

Un correttivo è che la classe è responsabile di garantire che la sua rappresentazione interna rimanga "valida". Supponiamo che una classe memorizzi un numero di telefono (semplificato) in due numeri interi:

    int areacode;
    int number;

Questi sono i membri dei dati della classe. Tuttavia, la classe sarà probabilmente molto più di solo i suoi membri di dati, e non è certamente definibile come "insieme di tutti i valori possibili di int x int". Non dovresti avere accesso diretto ai membri dei dati.

La costruzione di un'istanza potrebbe negare qualsiasi numero negativo. Forse la costruzione normalizzerebbe anche l'areacode in qualche modo, o addirittura verrebbe verificato l'intero numero. Ti ritroverai quindi molto più vicino al tuo "(a,b) where a is an int and b is a double" , perché non è certamente qualsiasi due int memorizzato in quella classe.

Ma non importa quanto riguarda la classe. Non è né il tipo dei membri dati, né l'intervallo dei loro possibili valori che definisce la classe, sono i metodi che sono definiti per esso.

Fintanto che questi metodi rimangono gli stessi, l'implementatore potrebbe cambiare i tipi di dati in virgola mobile, BIGNUM, stringhe, qualunque cosa, e per tutti gli scopi pratici, sarebbe ancora la stessa classe .

Ci sono schemi di progettazione per garantire che tali cambiamenti della rappresentazione interna possano essere fatti senza che il cliente ne sia consapevole (ad esempio l'idioma pimpl in C ++, che nasconde tutti i membri dei dati dietro a puntatore opaco ).

    
risposta data 21.01.2015 - 16:50
fonte
2
  • Un tipo è una descrizione di una categoria / intervallo di valori, strutture composte o cosa hai. OOPwise, è simile a una "interfaccia". (Nel senso linguaggio-agnostico, il significato specifico del linguaggio, non tanto: in Java, ad esempio, int è un tipo , ma non ha alcuna relazione con un interface . Pubblico / anche le specifiche del campo protetto non fanno parte di interface , ma sono parte di una "interfaccia" o tipo .)

    Essendo il punto principale, è molto più una definizione semantica che una concreta. Struttura solo fattori in quanto i campi / comportamenti esposti e i loro scopi definiti si allineano. Se non hai entrambi, non hai compatibilità di tipo.

  • Una classe è la realizzazione di un tipo. È un modello che definisce in realtà la struttura interna, il comportamento allegato, ecc.

risposta data 21.01.2015 - 20:45
fonte