Italian [B4A] Il nome di una variabile non può coincidere con quello di una routine

Giorgio Brausi

Member
Licensed User
Longtime User
Salve,

ho aperto il progetto di esempio MyFirstProgram, nel Designer ho aggiunto un nuovo EditText (EditText1) e dal menu Strumenti -> Genera membri ho generato due membri: TextChanged e EnterPressed.

B4X:
Sub EditText1_TextChanged (Old As String, New As String)
  
End Sub

Sub EditText1_EnterPressed
  
End Sub

Poi ho aggiunto nella Sub Globals la dichiarazione
B4X:
Private EditText1 As EditText


L'EnterPressed è ok.
Il TextChanged invece appare sottolineato in rosso ed il messaggio nel tooltip mi comunica:
Il nome di una variabile non può coincidere con quello di una routine
e non riesco a capire come mai.

Questo è l'output della compilazione:

B4A Versione: 8.50
Analisi del Codice. (0.00s)
Building folders structure. (0.02s)
Compilazione del codice. Error
Errore nella compilazione del programma.
Descrizione dell'errore: Il nome di una variabile non può coincidere con quello di una routine. (new).
Errore nella linea: 79
Sub EditText1_TextChanged (Old As String, New As String)
Word: edittext1_textchanged

Ho provato diverse volte ad eliminare, chiudere il progetto, riaprirlo e ricreare ma si verifica sempre lo stesso problema.
Inizialmente, sempre con lo stesso progetto, questo non accadeva.

Cosa può essere?

EDIT
Facendo una ricerca trai files della cartella MyFirstProgram ho trovato nel file \SourceCode\MyFirstProgram\Objects\shell\bin\classes\b4a\MyFirstProgram1\main_subs_0.class la stringa

_edittext1

Ho l'impressione che c'entri qualcosa.
Se ho ragione, posso cancellare il file?
Ma poi perché nella cartella \classes\ ho due cartelle MyFirsProgram e MyFirsProgram1 ?
 
Last edited:

klaus

Expert
Licensed User
Longtime User
This sounds very strange.
Can you upload your project as a zip file, so we can see what exactly you have done and how.

upload_2018-11-9_10-28-47.png


You can also close the IDE, delete the Objects folder and delete this file MyFirstProgram.b4a.meta and reload the project in the IDE.
 

Giorgio Brausi

Member
Licensed User
Longtime User
Unfortunately I've deleted previous project.
I unpacked the original project again and again create the EditText, getting the same problem.

MyFirstProgram.png
 

Attachments

  • MyFirstProgram.zip
    7.8 KB · Views: 213

Giorgio Brausi

Member
Licensed User
Longtime User
Sorry but I don't understand...
The Subs were created by B4A Designer: Tools->Generate Members menu don't by me.
 

PCastagnetti

Member
Licensed User
Longtime User
Hai una sub New che coincide con il parametro New dell'evento textchanged.
Rinomina Sub New in New2 ( e le relative chiamate)
B4X:
Sub New2
    Number1 = Rnd(1, 10)            ' Generates a random number between 1 and 9
    Number2 = Rnd(1, 10)            ' Generates a random number between 1 and 9
    lblNumber1.Text = Number1        ' Displays Number1 in label lblNumber1
    lblNumber2.Text = Number2        ' Displays Number2 in label lblNumber2
    lblComments.Text = "Enter the result" & CRLF & "and click on OK"
    edtResult.Text = ""            ' Sets edtResult.Text to empty
End Sub
 

Giorgio Brausi

Member
Licensed User
Longtime User
Perché poi ho scritto in inglese? :p
Probabilmente a seguito dell'intervento di Klaus :D

Hai una sub New che coincide con il parametro New dell'evento textchanged.
Rinomina Sub New in New2 ( e le relative chiamate)
Hai proprio ragione. Il problema è quello.
Però onestamente, questo mi sconcerta non poco!!!
Un parametro (in questo caso New As String) indicato nella firma di una routine dovrebbe essere locale.
Il fatto che sia considerato pubblico mi lascia molto molto perplesso...

In 30 anni che sviluppo software in vari linguaggi non mi era mia accaduto una cosa del genere (fino ad ora). Assurdo!
Francamente, lo considero un bug del linguaggio B4A.


In ogni caso Grazie infinite. :)
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Un parametro (in questo caso New As String) indicato nella firma di una routine dovrebbe essere locale.
Il fatto che sia considerato pubblico mi lascia molto molto perplesso...
Infatti il parametro è locale, mentre la SUB NEW è pubblica. E' la sub che essendo pubblica all'interno di EditText1_TextChanged va in conflitto con la variabile Locale
potevi anche fare così e funzionava lo stesso:
B4X:
Sub EditText1_TextChanged (OldText As String, NewText As String)
 
End Sub
 

Giorgio Brausi

Member
Licensed User
Longtime User
Infatti il parametro è locale, mentre la SUB NEW è pubblica. E' la sub che essendo pubblica all'interno di EditText1_TextChanged va in conflitto con la variabile Locale
potevi anche fare così e funzionava lo stesso:
B4X:
Sub EditText1_TextChanged (OldText As String, NewText As String)
 
End Sub
Ma se il parametro è locale come fa an andare in conflitto con una ruotine esterna, e viceversa, pur se dichiarata pubblica?
Non ha senso.
Questo va in conflitto con le regole di incapsulamento della programmazione ad oggetti.

In VB.NET questo codice viene eseguito senza problemi:
B4X:
Public Class Form1
    Function MyVar(ByVal pParameter As Integer) As String
        If pParameter = 1 Then
            Return "First"
        Else
            Return "Last"
        End If
    End Function
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        MessageBox.Show(MyVar(1)) ' mostra "First"
    End Sub

    Private Sub EditText1_TextChanged(sender As Object, MyVar As EventArgs) Handles EditText1.TextChanged
        MessageBox.Show(MyVar.ToString) ' mostra: "System.EventArgs"
    End Sub
End Class

Ma stessa cosa in C#, e persino in VB6.
 

Star-Dust

Expert
Licensed User
Longtime User
Secondo me ti sbagli. Se chiamo New all'interno di EditText1_TextChanged, mi potrei riferire alla variabile locale ma potrei voler richiamare la sub pubblica all'interno di TextChanged.

In VB6, con MyVar indichi la variabile locale ma non potrai richiamare la funzione che ne porta lo stesso nome all'interno della EditText1_TextChanged. Quindi se lo volessi fare (richiamare la sub MyVar), dovresti sempre cambiare nome a una delle due.

L'incapsulamento non mi sembra che ci entri molto in questo discorso.

Comunque importante che hai trovato la risposta alla tua domanda e puoi proseguire.
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
In B4A le variabili sono alquanto strane, in effetti. Se dichiari un array a livello globale, diciamo di 10 elementi, poi ne dichiari uno locale, in una routine, di 20 elementi, in realtà hai modificato quello globale, che sarà di 20 elementi (questo senza il Redim di VB.Net e tantomeno il Preserve).
 

Giorgio Brausi

Member
Licensed User
Longtime User
In B4A le variabili sono alquanto strane, in effetti. Se dichiari un array a livello globale, diciamo di 10 elementi, poi ne dichiari uno locale, in una routine, di 20 elementi, in realtà hai modificato quello globale, che sarà di 20 elementi (questo senza il Redim di VB.Net e tantomeno il Preserve).

Addirittura? Andiamo bene... :confused:

@Star-Dust Ecco cosa c'entra incapsulamento. Quindi c'entra, eccome se centra.
Comunque hai detto bene, la risposta l'ho trovata, dovrò agire di conseguenza.

Grazie a tutti. :D
 

MarcoRome

Expert
Licensed User
Longtime User
Nessun errore e nessuna stranezza.
Come dice Erel QUI

This is a new and very important check. Your current code would have called the Destination method instead of getting the variable value (at least in some cases).

Infatti nella "Visibilità" delle Variabili Globali:

una variabile globale non è utilizzabile in una procedura se nella procedura viene definita un'altra variabile con lo stesso nome.

LEGGI QUI

Quindi il buon Erel per evitare "errori" e tagliare la testa al toro ha inserito questo check ( ben fatto ). E' più comodo avere un messaggio dato nel check "Variable name cannot be the same as sub name" che incorrere in un eventuale e "subdolo" errore.
 

udg

Expert
Licensed User
Longtime User
Scusate, dico la mia con riferimento in particolare ai post #12 e #13.
In generale dovrebbe essere possibile, senza alcuna confusione di sorta da parte del compilatore, utilizzare per una variabile lo stesso identificativo utilizzato per il nome di una funzione. La ratio sta nel fatto che il compilatore dovrebbe comprendere, senza alcuna difficoltà, che si trova nella parte dichiarativa del metodo e quindi ovviamente l'identificativo è una variabile locale. Mi spiego con l'esempio di cui sopra:

Sub EditText1_TextChanged (OldText As String, New As String)
...
New = "abc"
..
End Sub

Public Sub New(myParam as Int)
..
End sub

In questo caso "New" (in TextChanged) è necessariamente la dichiarazione di una variabile locale e non la chiamata ad una funzione di nome New. E non vedo come il compilatore possa confondersi.
Se nel corpo di TextChanged avessi un New = "abc" teoricamente il compilatore potrebbe essere confuso e non sapere se mi sto riferendo alla variabile locale New (ed in tal caso l'assegnazione è ok) oppure sto chiamando in modo errato la funzione New (e quindi avvisarmi con warning o errore).
La cosa si risolve facilmente differenziando tra:
New = "abc" <-- new variabile locale
<module name>.New(58) <-- chiamata a funzione di nome New definita nel modulo X

Ho utilizzato impropriamente il termine funzione per la public New laddove sarebbe stato più corretto parlare di procedura (le mie radici sono nel Pascal) o metodo.

E se a runtime volessimo (corretti i tipi e le definizioni in modo opportuno) chiamare TextChanged passando come secondo parametro il risultato della funzione?
Scriveremmo TextChanged("old1", Main.New(77)), ancora una volta senza possibilità di confusione.

Ad ogni modo, direi che le spiegazioni fornite da Marco siano valide e condivisibili. Dobbiamo ricordare che B4X è un linguaggio di suo, non è Pascal, C. C#, VB etc etc e quindi è giusto che abbia le sue regole. Come abbiamo accettato quelle degli altri, ora possiamo serenamente uniformarci a quelle di B4x.

ps: lasciate che in questa occasione io possa esprimere il mio ringraziamento al prof. Niklaus Wirth per avere ideato, tra le altre cose, il linguaggio Pascal, il mio primo vero amore (informatico..lo preciso per @LucaMs, che non si sa mai..ehehe)
 
Top