I'm trying to use classes and reference them within each other. Unfortunately I can't seem to figure it out how. What I try to do is:
Create a module exporting classes in different files. One of the classes has a method which returns another class.
Import the module in another class and make use of the classes from the module.
What I tried (simplified example):
Item.ps1
class Item {
}
ItemList.ps1
. '.\Item.ps1'
class ItemList {
[Item] function Items () {
// It goes wrong here. Visual studio code mentions type Item cannot be found.
}
}
Utilities.psm1
. '.\Item.ps1'
. '.\ItemList.ps1'
// I'm not sure if this is the right way to export the classes via the module
Foo.ps1
using module '.\Utilities.psm1'
class Foo {
[ItemList] function CreateItemList() {
// It goes wrong here. Visual studio code mentions type ItemList cannot be found.
}
}
I would really appreciate if some could help me figure this out!
Update
It looks like it can't be done. Here the following is mentioned:
In this release, you can't use a type literal (for example, [MyClass]) outside the script/module file in which the class is defined.
Related
I'm facing an issue where I'm trying to split the code up into different files (to make it neater). So far the import is working except for one file.
Currently, my flutter project is setup in this manner
However, one of my files is not importing correctly.
This is my chorusSearch.dart file:
I've tried importing a class from chorusPage.dart. But the import is not resolving.
What is wrong here? This is my chorusPage.dart file.
You cannot call a method or a function of a class that should be instantiated.
You are trying to access a method inside a private class (with the _ char before) of a class that should be initialized before.
If you want to create functions that don't require a view, a page and nothing visual you should make public and static classes and create something like an utility.dart class that contains them.
Then you can call Utility.yourfunction() from where you want
A little example
file utility.dart in lib/utils/
void your_method() {
//do something
}
then in place you can import the file utility.dart and you can also assign to it a name with "as" like this -> import 'package:appname/utils/utility.dart' as Utility;
then you can use Utility.your_method()
Overview
I have written a babel plugin that adds a custom constructor to classes. I also use the #babel/plugin-proposal-class-properties plugin to support class properties. My .babelrc looks like this:
{
"plugins": [
"./plugins/my-plugin.js",
"#babel/plugin-proposal-class-properties",
]
}
I'm using babel-core#7.2.2, and #babel/plugin-proposal-class-properties#7.2.3.
The issue
The class properties plugin overwrites my generated constructor. For example, given this test file:
// Source
class Test extends Base {
// someProp = 'yay';
}
If I run without the class properties plugin, my constructor is inserted:
// Transpiled (no class props)
class Test extends Base {
constructor() {
super(...arguments);
console.log('my special custom code');
}
}
But if I uncomment someProp and enable the class properties plugin, my custom code is overwritten:
// Transpiled (with class props)
class Test extends Base {
constructor(...args) {
super(...args);
_defineProperty(this, "someProp", 'yay');
}
}
It doesn't seem to matter what order I list the plugins. Is this expected, is there a way around it, or is this a bug?
I don't think the implementation of my plugin matters - but if it does, I can add more detail.
Any help appreciated. Thanks!
I ended up asking for help in the Babel slack community, and they were able to help me fix this issue.
The problem was that I was using a different visitor in my implementation - I had visitors specified for ClassDeclaration and ClassMethod, but the visitor in the plugin-proposal-class-properties implementation was on Class. When I changed my code to work off of Class, and made sure mine ran first, the properties were added to my custom constructor as expected.
I know this was aksed and answered a a couple of times e.g.
Solution-wide #define, Is There anyway to #define Constant on a Solution Basis? and How to define a constant globally in C# (like DEBUG).
But in my case I can not use any of the suggested methods:
I'm writing on different "modules" (or plugins if you want so) for UnityProjects (kind of a package providing a certain functionality). The idea is that a developer can load a certain "module" to use in his project by importing a UnityPackage with all scripts and resources in it.
But some of these modules themselves depend on other modules. So what I tried so far was having a class Constants in each module with seperated namespaces and preprocessor definitions.
Module A
#if !MODULE_A
#define MODULE_A // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
namespace Module_A
{
public static class Constants
{
// some constants for this namespace here
}
}
Module B
#if !MODULE_B
#define MODULE_B // BUT I WOULD NEED THIS GLOBAL NOT ONLY HERE
#endif
#if !MODULE_A // WILL BE NOT DEFINED OFCOURSE SINCE #define IS NOT GLOBAL
#error Module A missing!
#else
namespace Module_B
{
public static class Constants
{
// some constants for this namespace here
}
// and other code that might require Module A
}
#endif
But ofcourse this cannot work like this since #defines are not global but only in the current file.
Problem
For this whole idea of modules and a simple "load your modules" I can not ask the user to first make changes to the project or solution settings how e.g. suggested by this answer but instead have to use only the (c#) resources that come imported with the UnityPackage (at least with my current know-how).
Is there any way to somehow set/define those constants for the entire Unity-Project by only importing the module's UnityPackage?
Edit:
I could find a solution for 1 definition in Unity using Assets/msc.rsp. But this still wouldn't work for multiple modules since they would have to write into the same file.
After a lot of searches I've finally been able to put together a surprisingly simple solution I'ld like to share with you:
InitializeOnLoad
Unity has an attribute [InitializeOnLoad]. It tells Unity to initialize according class as soon as
Unity is launched
After any re-compiling of scripts => also after importing a new unitypackage with scripts
static Constructor
In their Running Editor Code On Launch example, they show, how to combine this with a static constructor.
From static-constructors:
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
While usually you still would have to create an instance of the class, the static constructor is "instanciated/executed" instantly when the class is initliazed, which we force using the [InitializeOnLoad] attribute.
Scripting Define Symbols
Further Unity actually has project wide defines in the PlayerSettings.
And the good part is: We also have access to them via scripting API:
PlayerSettings.GetScriptingDefineSymbolsForGroup
PlayerSettings.SetScriptingDefineSymbolsForGroup.
So what I did now is the following
Module A
This module has no dependencies but just defines a "global define" in the PlayerSettings. I placed this script somewhere e.g. in Assets/ModuleA/Editor (important is the last folder's name).
using System.Linq;
using UnityEditor;
namespace ModuleA
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#region Add Compiler Define
// Get the current defines
// returns a string like "DEFINE_1;DEFINE_2;DEFINE_3"
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
// split into list just to check if my define is already there
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_A")
{
// if not there already add my define
defines += ";MODULE_A";
}
// and write back the new defines
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endregion
}
}
}
Module B
This module depends on Module A. So itself defines a "global define" (so later Modules can check their dependecies on Module B) but additionally it checks first, if Module A is imported. If Module A is missing, it prints an error to the Debug Console.
(You could as well throw a compiler error using #error SOME TEXT, but for some reason this is not capable of printing out the URL correctly so I decided for the Debug.LogError)
I placed this script somewhere e.g. in Assets/ModuleB/Editor
#if MODULE_A
using System.Linq;
#endif
using UnityEditor;
#if !MODULE_A
using UnityEngine;
#endif
namespace ModuleB
{
// Will be initialized on load or recompiling
[InitializeOnLoad]
public static class Startup
{
// static constructor is called as soon as class is initialized
static Startup()
{
#if !MODULE_A
Debug.LogErrorFormat("! Missing Module Dependency !" +
"\nThe module {0} depends on the module {1}." +
"\n\nDownload it from {2} \n",
"MODULE_B",
"MODULE_A",
"https://Some.page.where./to.find.it/MyModules/ModuleA.unitypackage"
);
#else
// Add Compiler Define
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
var define = defines.Split(';').ToList();
if (!define.Contains("MODULE_B"))
{
defines += ";MODULE_B";
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
#endif
}
}
}
So later in other scripts of Module B I have two options (both do basically the same)
I can either check everywhere #if MODULE_A to check exactly the module this script relies on
or I can instead check #if MODULE_B to rather check with one line if all dependecies are fulfilled since otherwise I don't define MODULE_B.
On this way I can completely check all dependencies between certain modules which is awesome. The only two flaws I saw until now are:
We have to know how the define (e.g. MODULE_A) looks like for every module and if it is changed in the future it has to be changed in all depending modules as well
The "global define" isn't getting removed in case the module is deleted from the project
But well - which solution is perfect?
In general, the way I would solve this problem in C# is by defining a common set of interfaces that all your modules would contain. I think you can do this with Unity by placing the files from each module in the same location, thus allowing later installations to overwrite those same files (with, obviously, the same content). You would then put editor controls that expose properties to hold instances of those interfaces and then wire them up in the UI. You would test those properties for a value of null to determine which ones are missing.
Common.cs:
public interface IModuleA {}
public interface IModuleB {}
ModuleA.cs
public class ModuleA : IModuleA {}
ModuleB.cs
public class ModuleB : IModuleB
{
public IModuleA ModuleAInstance {get; set;}
private bool IsModuleAPresent()
{
return !ModuleAInstance == null;
}
}
The ideal way to solve it would be with a package manager and proper dependency injection, but doing that with Unity is not straightforward.
Edit: So far it looks like the answer to my question is, "You can't do that in Swift." I currently have a solution whereby the subclass names are listed in an array and I loop around and instantiate them to trigger the process I'm describing below. If this is the best that can be done, I'll switch it to a plist so that least it's externally defined. Another option would be to scan a directory and load all files found, then I would just need to make sure the compiler output for certain classes is put into that directory...
I'm looking for a way to do something that I've done in C++ a few times. Essentially, I want to build a series of concrete classes that implement a particular protocol, and I want to those classes to automatically register themselves such that I can obtain a list of all such classes. It's a classic Prototype pattern (see GoF book) with a twist.
Here's my approach in C++; perhaps you can give me some ideas for how to do this in Swift 4? (This code is grossly simplified, but it should demonstrate the technique.)
class Base {
private:
static set<Base*> allClasses;
Base(Base &); // never defined
protected:
Base() {
allClasses.put(this);
}
public:
static set<Base*> getAllClasses();
virtual Base* clone() = 0;
};
As you can see, every time a subclass is instantiated, a pointer to the object will be added to the static Base::allClasses by the base class constructor.
This means every class inherited from Base can follow a simple pattern and it will be registered in Base::allClasses. My application can then retrieve the list of registered objects and manipulate them as required (clone new ones, call getter/setter methods, etc).
class Derived: public Base {
private:
static Derived global; // force default constructor call
Derived() {
// initialize the properties...
}
Derived(Derived &d) {
// whatever is needed for cloning...
}
public:
virtual Derived* clone() {
return new Derived(this);
}
};
My main application can retrieve the list of objects and use it to create new objects of classes that it knows nothing about. The base class could have a getName() method that the application uses to populate a menu; now the menu automatically updates when new subclasses are created with no code changes anywhere else in the application. This is a very powerful pattern in terms of producing extensible, loosely coupled code...
I want to do something similar in Swift. However, it looks like Swift is similar to Java, in that it has some kind of runtime loader and the subclasses in this scheme (such as Derived) are not loaded because they're never referenced. And if they're not loaded, then the global variable never triggers the constructor call and the object isn't registered with the base class. Breakpoints in the subclass constructor shows that it's not being invoked.
Is there a way to do the above? My goal is to be able to add a new subclass and have the application automatically pick up the fact that the class exists without me having to edit a plist file or doing anything other than writing the code and building the app.
Thanks for reading this far — I'm sure this is a bit of a tricky question to comprehend (I've had difficulty in the past explaining it!).
I'm answering my own question; maybe it'll help someone else.
My goal is to auto initialize subclasses such that they can register with a central authority and allow the application to retrieve a list of all such classes. As I put in my edited question, above, there doesn't appear to be a way to do this in Swift. I have confirmed this now.
I've tried a bunch of different techniques and nothing seems to work. My goal was to be able to add a .swift file with a class in it and rebuild, and have everything automagically know about the new class. I will be doing this a little differently, though.
I now plan to put all subclasses that need to be initialized this way into a particular directory in my application bundle, then my AppDelegate (or similar class) will be responsible for invoking a method that scans the directory using the filenames as the class names, and instantiating each one, thus building the list of "registered" subclasses.
When I have this working, I'll come back and post the code here (or in a GitHub project and link to it).
Same boat. So far the solution I've found is to list classes manually, but not as an array of strings (which is error-prone). An a array of classes such as this does the job:
class AClass {
class var subclasses: [AClass.Type] {
return [BClass.self, CClass.self, DClass.self]
}
}
As a bonus, this approach allows me to handle trees of classes, simply by overriding subclasses in each subclass.
According to http://www.gebish.org/manual/current/modules.html#modules
Modules should be defined like this:
class ExamplePage extends Page {
static content = {
theModule { module ExampleModule }
}
}
From Geb's Documentation:
16.2.2 Strong typing
In order to gain improved authoring support, you must include types in
your tests and page objects. Additionally, you must explicitly access
the browser and page objects instead of relying on dynamic dispatch.
So:
HomePage homePage = browser.to HomePage
homePage.loginButton.click()
It's works fine for Pages, but can i find the way to have it with Modules aswell?
to have autocompletion here:
HomePage homePage = browser.to HomePage
homePage.loginFormModule. *autosuggestion here*
(where "loginFormModule" - is module of HomePage)
Stronger typing for module definitions has been recently added to master but hasn't been released yet. Basically the location of module() method has changed so that now IntelliJ understands the return type of it. If you wish to give it a try then you can use 0.10.1-SNAPSHOT from Geb's snapshot repo. The way you pass a base navigator and parameters to a module has changed, see the latest chapter on modules for info. It would be awesome if you could give it a try and tell me if by simply changing the version you get autocompletion.