What are the potential consequences of setting a class to PublicNotCreatable? - vba

Say I have a class TestClass with the following definition:
Option Explicit
Public x As Variant
I want an instance of this class to be created when the workbook opens, and usable in other workbook events. So in the ThisWorkbook module, I add:
Public tc As TestClass
Private Sub Workbook_Open()
Set tc = New TestClass
tc.x = "abc"
End Sub
When I compile this, I get an error:
Private object modules cannot be used in public object modules as
parameters or returns types for public procedures, as public data
members, or as fields of public user defined types
I was able to resolve this by going to the Properties Window for TestClass and setting Instancing to PublicNotCreatable. It seems that this hasn't affected the behavior of the class or my ability to create local instances of it within various functions in this VBA project. Does changing this Instancing setting have any potential problems?

PublicNotCreatable is so you can use that class in a different VBProject. The NotCreatable part means that whatever VBProject hosts the class has to create any new instances and pass those to the other VBProject. The other VBProject cannot create them by itself.
What you want to do is Public tc As TestClass in a standard module and keep your class instancing Private. Declaring a variable public in a standard module makes that variable available everywhere in your project.
What you did is created a custom property of the ThisWorkbook instance of the Workbook object. ThisWorkbook is a class module (so are the sheet modules and userforms). Those class modules are special because they have a user interface component (workbooks, worksheets, and forms), but they're class modules all the same. You can define properties and methods in ThisWorkbook just like you do in a custom class. And that's what you did. You created a custom property called tc.
To create a property in a class, you can either use Property Get/Let or Public. The shortcut of using Public looks a lot like declaring a public variable in a standard module, but it's not quite the same.
So why the error? When your custom class instance is a property of another class, VBA won't let you create an instance of the custom class because you could end up with a child class and no parent class.
So keep your instancing private and declare your public variables in a standard module. I have a special module called MGlobals where I keep all my public variables. If I have more than a couple, I'm probably doing something wrong.

Related

How to get the class type of a calling class in a method call in a different referenced project

My solution is called "PlasmaBlueTooth_Soln" and there are many projects included in the solution.
One of the projects is called "PlasmaBluetooth" and contains many classes and a module and is the startup project for the application
(The module "startUpModule" contains the Main sub that starts the application.).
I have a class MainFormTestClass in the "PlasmaBluetooth"
that inherits a windows form MainForm.
I created many UserControls in separate projects that are used in the MainFormTestClass by instantiating a variable in MainFormTestClass, as the userControl in the separate projects then adding the instantiated control to the MainForm window controls.
The UserControl projects are referenced in the "PlasmaBluetooth" project. I have a method PerformAction in MainFormTestClass that calls a method
UserControlAction in a usercontrol class with an argument of Me.
I would like to use the MainFormTestClass Type in the method
UserControlAction(byref MeData as MainFormTestClass) However, the MainFormTestClass Type is not defined in the userControl project.
How do I get the MainFormTestClass Type in the UserControl project ?

Change attribute/getter/setter visibility in abap persistent class

Is there a possibility to change the visibility of the setter/getter from an attribute without changing attribute visibility?
e.g in Java I can say:
attribute: private
setter: protected
getter: public
That is very practic if I want to allow only in private scope changes, in protected scope I allow changes via setter (some checks and verifications in there) and in public scope you can only read.
In the classbuilder you can only change all of them together.
You can make the attribute public and change it to read-only in the persistence mapping - this will prevent the setter from being generated. You can change the attribute visibility in the class builder or the persistence mapping, which will affect both the setter and the getter. As far as I know, there are no other ways to affect the visibility. For a greater control, I'd recommend wrapping the persistence class - either in a separate class or by introducing a public getter-only interface whose methods defer to the generated getters.
Yes, it is possible. Just make use of this button.
And then change the visibility

.NET: Best practice for setting properties of main form from module

I have a main form.
The logic of my application is huge. I have around 100 modules in my application.
In some modules I need to set some properties of the main form's controls.
I feel that calling something like
Public Module SomeStuff
Public Sub DoSomething
frmMain.MyControl.Location = ...
End Sub
End Module
... is really dirty.
However, I can not move everything from the modules into the main form.
Is there any best practice to deal with such situation?
Edit: My code works, but it just feels ugly.
Thank you!
There's a number of options for setting properties on a form from a module, including:
Passing an instance of the form or form controls to a module function to be set
Returning the values from a module function to be set on the form
Form as an argument
The form or specific form controls could be passed as an argument to the module which sets the properties. This way you are not tied to a static instance of the form. However your functions may still be tightly coupled to the UI which may make them harder to unit test.
Returning values
To keep separation between the business logic and the UI, you could return the values that need to be applied to the form via a struct, class or dictionary. Then define a method or function to bind the values to the form controls.

Can't access methods from another class - VB

Example ^. I must be forgetting something or being really dumb.
You're accessing from the class, not the object, that's why only class methods get shown. Create inbox object first and use that to call the instance method.
Yep. You're referencing the class, not the object.
inbox = new Inbox()
inbox.getEmail()
create an object of Inbox class and then access it. If you want to access with Class name then you need to make the access member static.

When should a class use its own getters/setters vs accessing the members directly?

When generating setters and getters in Eclipse one of the options is to use the getters and setters within the class rather than accessing the class members directly. Is this level of class internal encapsulation useful or is it taking a good idea one step too far?
DUPE: Should you use accessor properties from within the class, or just from outside of the class?
I think it's a good idea if you want the potential side-effects to occur - validation, logging etc. (In C# I'd like to be able to declare a variable and property and say that the only access to the variable is through the property.)
Occasionally you may well find you need to set the variable directly precisely because you don't want the side-effects. For instance, you may need to set two variables together, and both the "before" and the "after" states are valid, but setting either property individually would make validation blow up.
It can be useful, if you allow derived classes to re-define your getters. So, using getters even from inside the class will keep your design extensible.
In my opinion this is something that needs to be defined in the coding guidelines.
The short answer is "it depends" :)
Eric Lippert has an excellent article on Automatic vs. Explicit properties that deals with this issue, albeit from a slightly different angle.
Essentially, the question you need to ask is:
"From within the class, [are] the desired semantics of accessing this ... property different from the desired semantics of accessing the property from the outside?"
If the semantics are the same, your class should use its own properties. If the semantics are different, your class will need to directly manipulate the backing fields.
It's useful for example when you have setters which do extra actions like setting a dirty flag or notifying observers.
For getters you may instead of accessing a field compute a value when you change representation.
When you need to extend the getter/setter behavior of a class, it is useful have encapsulated fields (getters/setters instead of direct member access).
Yet in inheritance, it is conceptualy interesting to preserve the inners of your class, if its subclasses shouldn't be aware of its private stuff. So, sometimes the field is private to the implementation of a class, so that even the subclasses aren't aware of it.
I find that I do that at times - specifically when I require, or strongly anticipate that I'll require, some login around getting or setting (and the validation around them) of members.
I find that having private/internal properties does help in these cases.
But I certainly not do it for any memeber.
Latest .NET/VS really helps here as you can declare a property as such:
public string SomeProperty
{
get;
set;
}
and it effectively creates the memebr behind the scene. I know that doesn't help you, but I thought it might be of some interest :-)
If you want for this member to be databindable by either Winform or WPF, I believe that you need to declare it as a property. I'm about 95 percent positive that databinding requires a property (getter/setting syntax). I have a small wpf solution that demonstrates this, but I don't see a way to attach it here.
Here's the code: (built with VS 2008 SP1, targeting .net 3.5 - I used a WPF Project).
There are 2 items in the WPF project, the main window (window1), and the object that we are testing (DataObject)
There is a label on the window that is databound to the Name property in an instance of data object. If you convert the Name property to a field (remove the getter/setter), the databinding will stop working.
Window1.xaml:
<Window x:Class="WpfDatabinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Label Name ="Label1" Height="28" Margin="12,24,37,0" VerticalAlignment="Top" Content="{Binding Name}"></Label>
</Grid>
Window1.xaml.cs
using System;
using System.Windows;
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
namespace WpfDatabinding
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataObject ADataObject;
public Window1()
{
InitializeComponent();
this.ADataObject = new DataObject();
this.ADataObject.Name = "Hello!";
this.DataContext = this.ADataObject;
}
}
}
DataObject.cs:
namespace WpfDatabinding
{
public class DataObject
{
// convert this to a field, and databinding will stop working
public string Name
{
get;
set;
}
}
}