Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

Bibliotheksverweise durcheinander ?!

Begonnen von Joe0301, Januar 16, 2017, 11:03:41

⏪ vorheriges - nächstes ⏩

MaggieMay

...ich schon, denn Properties sind nichts anderes als Eigenschaften, Methoden dagegen eher Prozeduren bzw. Funktionen. Wie da eine Property "eine Art Methode" sein könnte, ist für mich nicht nachvollziehbar
Freundliche Grüße
MaggieMay

Lachtaube

Außer der Semantik gibt es keinen Unterschied zwischen Properties und Methoden.Option Compare Database
Option Explicit

Private mFoo
Private mBar

Public Property Get Foo()
   Foo = mFoo
End Property

Public Property Let Foo(mValue)
  mFoo = mValue
End Property

Public Function GetBar()
   GetBar = mBar
End Function

Public Sub SetBar(mValue)
   mBar = mValue
End Sub
FWIW: Wer sich mit der Implementierung von COM-Interfaces beschäftigt, wird feststellen oder wissen, dass Direct-Interfaces (abgeleitet von IUnkown) keine Properties enthalten können. Properties stehen erst in von IDispatch abgeleiteten Interfaces (via Invoke-Methode) zur Verfügung.
Grüße von der (⌒▽⌒)

Joss

Danke an alle für die Antworten,
und danke an Lachtaube für die ausführlichen Erklärungen.

Gruß
Josef

Joss

@Lachtaube,

nachdem du alles so schön erklärt hast, ;) möchte ich doch noch einmal auf meine Ausgangsfrage zurückkommen. Mir geht es um das oft diskutierte Thema, statt globaler Variablen z.B. Properties zu verwenden.

ZitatProperties in einem globalen Modul stehen anwendungsweit zur Verfügung (typische Beispiele: Datenbank-Instanz, Angemeldeter Benutzer, Bildschirmauflösung, Gewählte Sprachumgebung, etc.); Properties in einem Klassenmodul benötigen eine Klasseninstanz (i.d.R. Eigenschaften, die von Instanz zu Instanz variieren können).

Wenn ich nun statt der Variante mit dem Klassenmodul die Variante mit dem globalen Modul nehme, hätte ich doch weniger Schreibarbeit, weil ich

  • keine Objektvariable im Klassenmodul brauche, z.B. Public glob As Klasse1
  • das Klassenobjekt nicht setzen brauche, z.B. Set glob = New Klasse1
  • und beim Aufruf keine Klasse angeben muss, z.B. glob.Benutzer = "Foo"
Brauche ich dann das aufwändigere Klassenmodul überhaupt, so wie es in den ganzen Beispielcodes im Internet angepriesen wird?

@Joe0301,
ich hoffe du verzeihst mir, dass ich deinen Thread etwas "missbrauche". ;)

Gruß
Josef

Josef P.

Hallo!

ZitatMir geht es um das oft diskutierte Thema, statt globaler Variablen z.B. Properties zu verwenden.
Ein Beispiel:
Angenommen es gibt eine Tabelle in der Anwendungseinstellungen gespeichert sind. Diese Einstellungen je Einsatz der Anwendung unterschiedlich, aber einmal eingestellt ändern sich diese Werte nur selten - zumindest ändern sich diese Werte nicht während der Anwendungslaufzeit.
Man könnte bei Bedarf mit DLookup & Co. die Werte immer aus der Tabelle auslesen, oder man hält sich den Wert im Speicher, damit man nicht so oft auf die Tabelle zugreifen muss.

private m_TemplatePath as String

public Property Get TemplatePath() as String
    if len(m_TemplatePath) = 0 then
       m_TemplatePath  = ReadConfigDataFromTable("TemplatePath")
    end if
    TemplatePath = m_TemplatePath 
end Property


Im restlichen Code verwendest man die Property-Prozedur wie eine globale Variable.
Würde man eine globale Variable verwenden, müsste man sich darum kümmern, dass diese vor Verwendung initialisiert (mit passendem Wert befüllt) wurde.
Das übernimmt im obigen Fall die Property-Prozedur.

Ob diese Property-Prozedur in einem Standardmodul oder eine (selbstinstanzierenden) Klasse ist, ist meiner Meinung nach eher Geschmacksfrage.

Vergleich:
dim TemplateFile as String
TemplateFile = TemplatePath & "\Projekthandbuch.dotx"
' vs.
TemplateFile = Config.TemplatePath & "\Projekthandbuch.dotx"


Bei der Klassenvariante ist im Code vielleicht etwas besser erkennbar, dass das ein Wert aus der Anwendungskonfiguration ist.

mfg
Josef

Joss

Hallo Josef,
danke für deine Antwort,

Zitatoder man hält sich den Wert im Speicher

aber man könnte doch den Wert auch über eine globale Variable im Speicher halten, z.B.
Public TemplatePath As String

Private Sub Form_Open(Cancel As Integer)

If Len(TemplatePath) = 0 Then
   TemplatePath  = ReadConfigDataFromTable("TemplatePath")
End If

End Sub



Oder welchen Vorteil hat deine Variante Private m_TemplatePath As String

Public Property Get TemplatePath() As String

If Len(m_TemplatePath) = 0 Then
   m_TemplatePath  = ReadConfigDataFromTable("TemplatePath")
End If

TemplatePath = m_TemplatePath

End Property

gegenüber der obigen?

Gruß
Josef

Lachtaube

Im vorliegenden Fall sorgt der Code selbst für eine gültige Initialisierung. Im Fall einer globalen Variablen wärest Du selbst für die Initialisierung verantwortlich. Bei einer handvoll globaler Variablen stellt das auch nicht unbedingt ein Problem dar - bei größeren Projekten verliert man aber schnell die Übersicht und handelt sich vermeidbare Fehler ein.

Ich stelle hier einmal das Motto auf: Soviel globale Variablen wie nötig und nicht so viele wie möglich.
Grüße von der (⌒▽⌒)

Josef P.

#22
Bei der Variante mit der globalen Variable musst du im Code dafür sorgen, dass diese vor der ersten Verwendung befüllt ist.
Wenn du das z. B. über ein Startformular regelst, musst du bei jeder neuen globalen Variable dafür sorgen, dass diese im Startformular initialisiert wird, und du musst dafür sorgen, dass das Startformular immer geladen wird.
=> du musst also beim Erstellen einer neuen Variable daran denken, dass diese auch geladen wird. Wenn du die Property-Prozedur verwendest, denkst du automatisch daran, weil der Prozedur-Code dafür sorgt und musst dir im restlichen Code keine Gedanken machen, ob die Initialisierung schon gelaufen ist.

Würde durch einen Laufzeitfehler der Variableninhalt der globalen Variable gelöscht, kommt ein falscher Wert bei der nächsten Verwendung an - außer du prüfst immer ob ein gültiger Wert enthalten ist => genau das macht die Property-Prozedur auch - aber eben nur an einer Stelle und nicht verteilt auf den restlichen Code.

Mit einer Property-Prozedur kannst du geprüft Werte übermitteln - sei es bei der Ausgabe als auch bei der Annahme.

Beispiel:
public property get AuswertungsMonat() as long
   AuswertungsMonat = m_AuswertungsMonat
end property

public property Let AuswertungsMonat(byval NewValue as long)
   if NewValue < 1 or NewValue > 12 then
      err.Raise vbobjecterror, "AuswertungsMonat", NewValue & " ist kein gültiger Monat"
   end if
   m_AuswertungsMonat = NewValue
end property


Versuche das einmal mit einer globalen Variable umzusetzen und dabei sicherzustellen, dass an keiner einzigen Stelle im Code der Wert ungeprüft geändert wird.
Anm.: das gilt übrigens auch für die oben erwähnten Anwendungseinstellungen - diese Properties sind schreibgeschützt und können somit nirgends im Code irrtümlich verändert werden, solange es keine Let/Set-Prozedur gibt.

mfg
Josef


Joss

Hallo Lachtaube und Josef,

ich habe bisher nur den Code für die Steuerung der Properties gekannt, und immer wieder gehört, dass man sie "unbedingt ::)" statt globaler Variablen verwenden sollte, aber jetzt habe ich von euch mal praktische Gründe und Möglichkeiten (die Basics) für deren Verwendung erfahren.

Ich bedanke mich dafür.

Gruß
Josef