Quando deve essere definita una funzione che calcola la proprietà di un oggetto all'interno della stessa classe?

1

Come esempio qui sotto, la funzione isClient() deve far parte della classe Attendee ?

import Foundation

///A Node that can be used with the CriteriaEvaluator to determine if clients are present in a Meeting.
class ClientCriteria  : Node {

/**
 Calculates a score from 0..1 to identify the likelihood that a list of Attendees contains a client
 */
func score(attendees : [Attendee]) -> Double
{
    for attendee in attendees
    {
        if isClient(attendee: attendee)
        {
            return 1
        }
    }
    return 0
}

private func isClient(attendee: Attendee) -> Bool
{
    let IBMEmailRegex = "[\/\w+\s*]+\/IBM\@?\w*$"
    if attendee.email.contains(IBMEmailRegex) {
        return false
    }
    else{
        return true
    }
}

}

    
posta Declan McKenna 23.02.2017 - 15:46
fonte

4 risposte

3

isClient () è una funzione vera. Non si basa sullo stato e restituisce sempre lo stesso valore dato lo stesso input.

Questo significa che può essere utilizzato ovunque. Se è di valore altrove, prendi in considerazione di spostarlo nella super classe, o forse in una classe di utilità. Se qui è solo prezioso, allora tienilo qui per evitare il disordine. Puoi sempre spostarlo in un secondo momento se qualcun altro può utilizzarlo.

una preferenza personale minore: preferisco

return !attendee.email.contains(IBMEmailRegex) 

a ciò che hai qui. Preferisco il piccolo codice:)

    
risposta data 23.02.2017 - 16:04
fonte
2

Come notato in un'altra risposta, la funzione specifica non accede allo stato dell'oggetto. Pertanto può essere definito ovunque.

Ma qualsiasi funzione che accede allo stato dovrebbe essere definita nella classe stessa. Ecco di cosa tratta l'incapsulamento.

    
risposta data 23.02.2017 - 17:11
fonte
1

Il motivo per non renderlo un metodo di Partecipante non è perché non accederà ai dati di Partecipante, ma vorrebbe accedere ai dati dei partecipanti se fosse necessario renderlo membro di un metodo (indirizzo di posta elettronica). La maschera per il confronto è però abbastanza arbitraria, è conoscenza al di fuori del dominio del Partecipante. Questo è il motivo per cui non lo includeresti. La prossima cosa è aggiungere un metodo che controlla se il partecipante ha figli, che è un'altra cosa non correlata alla presenza e prima che tu lo sappia hai una lezione di Dio.

Quindi guarda l'ambito dei dati utilizzati. Se si tratta solo di materiale per i partecipanti, rendilo un metodo. Se è coinvolto un altro tipo di conoscenza, portalo fuori o immetti i dati stranieri nel metodo attraverso un argomento.

    
risposta data 24.02.2017 - 07:52
fonte
1

Una regola generale è che se un metodo non accede a self e non è lì per implementare / sovrascrivere un metodo protocollo / super-classe, allora è nella classe sbagliata. Se c'è una classe diversa in cui accederà a se stessa se è stata spostata lì, allora è lì che dovrebbe essere. In questo caso, isClient si basa su Attendee quindi dovrebbe essere associato a Attendee . Tuttavia, poiché non si basa su nessuno stato privato, dovrebbe essere inserito in un'estensione.

Lascia che ti spieghi il ragionamento per averlo reso un'estensione ... In definitiva, il metodo isClient come definito di seguito è una funzione globale che accetta un argomento ... L'unica differenza tra func Attendee.isClient: Bool e func isClient(attendee: Attendee) -> Bool è ciò che sembra al sito di chiamata. C'è nessuna altra differenza ! Inserendo il metodo in un'estensione, questo fatto è reso più evidente. (Se si trovasse sull'oggetto stesso, ciò implicherebbe che il metodo richieda che parti private della classe funzionino.)

Inoltre, dato che è O (1) e restituisce sempre lo stesso valore dato lo stesso input, dovrebbe essere definito come una proprietà calcolata:

extension Attendee {
    var isClient: Bool {
        let IBMEmailRegex = "[\/\w+\s*]+\/IBM\@?\w*$"
        return email.contains(IBMEmailRegex) == false
    }
}

Vedo che score non dipende da te stesso ... Forse il punteggio sta implementando un protocollo che non hai menzionato? In caso contrario, questo dovrebbe anche essere spostato fuori dalla classe, ma poiché la sua implementazione è O (n) dovrebbe essere una funzione:

extension Sequence where Iterator.Element == Attendee {
    /// Calculates a score from 0..1 to identify the likelihood that a list of Attendees contains a client
    func score() -> Double {
        return contains(where: { $0.isClient }) ? 1 : 0
    }
}

Forse ClientCriteria contiene una schiera di partecipanti? Se è così, allora lo lascerei nella classe ClientCriteria

class ClientCriteria : Node {
    private var attendees: [Attendees] = []
    /// Calculates a score from 0..1 to identify the likelihood that a list of Attendees contains a client
    func score() -> Double {
        return attendees.contains(where: { $0.isClient }) ? 1 : 0
    }
}

o

class ClientCriteria : Node {
    private (set) var attendees: [Attendees] = [] // at least the setter should probably be private.
}

extension ClientCriteria {
    /// Calculates a score from 0..1 to identify the likelihood that a list of Attendees contains a client
    func score() -> Double {
        return attendees.contains(where: { $0.isClient }) ? 1 : 0
    }
}
    
risposta data 03.05.2017 - 02:15
fonte

Leggi altre domande sui tag