I am developing a package for Flutter Apps
There are methods and classes that are useful only for the package itself, and not for the programmer who will import my package, is possible to hide this methods and classes for further implementation?
Example:
DataService.dart
export class DataService{
//Must be visible only for my library
static notifyDataChanged(InternalEvent internalEvent){ ... }
//Must be visible for anyone
static addCallbackOnDataChange(onDataChangeCallback) { ... }
}
InternalEvent.dart
//Must be visible only for my library as well
export class InternalEvent {
...
}
The usual approach to having package-only declarations is to put them in a library in the lib/src/ directory, and not export that library. The other libraries in the package can import the package-only library, but users outside the package are discouraged from importing libraries in lib/src/ directly. (It's not impossible, just something that's discouraged because the package is free to change those libraries without warning).
If the package-only features require access to library private parts of public classes, then they need to be in the same library. The traditional way is then to declare both in a library in lib/src/ and export only the parts of that library which needs to be public:
library myPackage;
export "src/allDeclarations.dart" hide Private, Declarations;
// or, preferably,
export "src/allDeclarations.dart" show Public, Things;
Generally you should only put exported and non-exported declarations in the same library if absolutely necessary. Otherwise the hide/show lists become too cumbersome and it's to easy to forget a declaration in a hide list.
You have a few possibilities:
Making a method/variable private, by prefixing it with _:
class _InternalEvent {}
Use the hide/show directives:
// lib/src/event.dart
class InternalEvent {}
class VisibleEvent {}
// lib/my_package.dart
export 'src/event.dart' hide InternalEvent;
OR
export 'src/event.dart' show VisibleEvent;
For package-private members exists an annotation, #internal.
Using #internal the analyzer emit a warning when:
you export the annotated element (from a file under lib)
a consumer of your package imports the annotated element
Anyway, Dart seems to me to make things really complicated. The need to have members who are neither completely public nor inaccessible from outside the file is elementary, yet no solution provides certainties.
Note that:
the doc says to keep the package-private elements in files under lib/src, yet the consumers of your package will still be able to import them, without even the analyzer producing a warning; it's just a convection;
using the #internal annotation, the analyzer (ie the ide, which rely on the analyzer) produces a warning, but nothing prevents you from compiling the code anyway. The situation improves a little if you increase the severity level of the warning produced by the analyzer when the annotation is not respected. To do this, you need to create an analysis_options.dart file like the following:
analyzer:
errors:
invalid_use_of_internal_member: error #possible values: ignore, info, warning, error
Note that the #internal annotation, like other similar ones (#visibleForTesting, #protected) is part of the meta package, which is included in the Flutter Sdk, but which must be included as a dependency in pure-dart packages.
its so simple
suppose i have a below code in src folder of your lib,
class myClass1 {}
class myClass2 {}
class myClass3 {}
below export statement will make all 3 classes visible/accesible
export 'src/mylib_base.dart' ;
below export statement will make myClass3 visible/accessible and remaining not accessible
export 'src/mylib_base.dart' show myClass3 ;
below export statement will make myClass3 not visible/accessible and remaining accessible
export 'src/mylib_base.dart' hide myClass3 ;
So simply
with hide classes/function ,hide those that you mention and remaining will be shown to end user
with show classes/function ,show those that you mention and remaining will be hide to end user
Related
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.
For example, I have two files called file1.swift and file2.swift.
file1.swift:
import UIKit
class A: B {
}
file2.swift:
import UIKit
class C: A{
}
I am reading that public class can not subclassed outside of module. Here I have subclass C. I am trying to understand what does module mean here. I imported to same module UIKit for both file. So the both files are of same module? So that I can subclassed. Or both files have different module even I import the same UIKit?
Can anybody explain what is module?
Source:
Classes with public access, or any more restrictive access level, can be subclassed only within the module where they’re defined.
Class members with public access, or any more restrictive access level, can be overridden by subclasses only within the module where they’re defined.
A module is a single unit of code distribution—a framework or application that is built and shipped as a single unit and that can be imported by another module with Swift’s import keyword.
Each build target (such as an app bundle or framework) in Xcode is treated as a separate module in Swift. If you group together aspects of your app’s code as a stand-alone framework—perhaps to encapsulate and reuse that code across multiple applications—then everything you define within that framework will be part of a separate module when it’s imported and used within an app, or when it’s used within another framework.
As the docs indicate, the module is an application or a framework (library). If you create a project with classes A and B, they are part of the same module. Any other class in the same project can inherit from those classes. If you however import that project to another project, classes from that another project won't be able to subclass A nor B. For that you would have to add open indicator before their declarations.
Basically, if you work on a single app then you are working in one single module and unless declared as private or fileprivate, the classes can subclass each other.
EDIT
Let us have following class in module (project) Module1:
class A {
}
Since this class is not open, it can be subclassed only within the same module. That means that following class:
class B: A {
}
Can be written only in the same project, in Module1.
If you add Module1 as a dependency to project Module2, and try to do this:
import Module1
class C: A {
}
It will not compile. That's because class A is not open (in other words it has access public or less) and it does not belong to the same module as C. A belongs to Module1, C belongs to Module2.
Note
import keyword imports a dependency module to your current module. If you write import UIKit in your project, you are telling the compiler that you want to use module UIKit in your module. import does not define current module. Current module is the current project.
Adding import UIKit at the beginning of the file does not change nor define to which module the file belongs. It just tells the compiler that in that file you want to use code from UIKit module.
Swift module(.swiftmodule)
History:
[#include -> #import] -> [Precompiled Headers .pch] -> [#import Module(ObjC);] -> import Module(Swift)
There are two type of Module - folder and file
.swiftmodule folder. Folder contains all .swiftmodule files for architectures and other meta information like:
.swiftmodule file. It is binary file format which contains Abstract Syntax Tree(AST) or Swift Intermediate Language(SIL) of framework's public API.
.swiftdoc - attached docs which can be revived by consumer
.swiftinterface - Module stability
[.swiftinterface or Swift Module Interfaces] is a next step of improving closed source compatibility
When you Jump to Definition of imported module actually you reviewing public interface of .modulemap
Binary(library, framework) can contains several modules, each module can contains a kind of submodule(from Objective-C world) thought.
import struct SomeModule.SomeStruct
These modules can have dependencies between each others.
Module is a set of source files which solves the same problem that is why they can be grouped under the same model name.
Module helps to group sources to reuse them
Module helps Xcode to minimize build time(open source)(If module was not changed it should not been recompiled)
Also Module is a kind of scope which can help compiler to figure out which exactly class to use. If two modules use the same name you get
Ambiguous use of 'foo()'
It can be solved by:
import ModuleName1
import ModuleName2
func someFunc() {
ModuleName1.SomeClass.foo()
ModuleName2.SomeClass.foo()
}
Lately i've been working a lot with Dagger 2 and I'm having this particular use case that I'm not able to do the way I want to for different reasons:
1) It's not possible; 2) I'm just not understanding the concepts behind scopes and components/subcomponents.
I have 3 Components: AppComponent, DBComponent, ActivityComponent.
I need to have my activity to inherit dependencies from AppComponent and DBComponent. This is my following setup:
AppComponent:
#Singleton
#Component(modules = { AppModule.class }) {
EventBus bus()
ActivityComponent plus(ActivityModule activityModule);
}
DatabaseComponent:
#Database
#Component(dependencies = AppComponent.class, modules = DatabaseModule.class) {
ActivityDependency activityDependency();
}
ActivityComponent:
#PerActivity
#Subcomponent(modules = ActivityModule.class) {
void inject(MainActivity activity);
}
When I inject bus() everything works fine but as soon as I try to inject ActivityDependency() it simply does not work. I cannot figure out why...
Please note: I've read about almost all the posts in here and outside explaining scopes, components and subcomponents and still I can't get my head wrapping around how to achieve what I wanted.
Note 2: I know one way to fix this which is to add DatabaseModule.class as a module in the AppComponent and remove DatabaseComponent from the equation. But I feel this will make AppComponent with too much information and this is not really the go to way.
inherit dependencies from AppComponent and DBComponent.
Wrong. You need to inherit dependencies from AppComponent, and the contents of the DBComponent should be a module of AppComponent.
Note 2: I know one way to fix this which is to add DatabaseModule.class as a module in the AppComponent and remove DatabaseComponent from the equation. But I feel this will make AppComponent with too much information and this is not really the go to way.
Yes, it is the go-to way if you're using scoped dependencies.
Think of dependency inheritance like the extends keyword in Java.
You cannot extend multiple classes with the same class, can you?
Similarly, you cannot extend multiple scoped components either.
So if you want your graph to provide bindings for a given scope, then your component needs to have all the modules for that given scope. And #Database isn't really a scope (think lifecycles), that's a renamed #Singleton.
I'm looking for a way of condensing some of my AS3 code to avoid almost duplicate commands.
The issue is that I have multiple variables with almost the same name e.g. frenchLanguage, englishLanguage, germanLanguage, spanishLanguage
My Controller class contains public static variables (these are accessed across multiple classes) and I need a way to be able to call a few of these variables dynamically. If the variables are in the class you are calling them from you can do this to access them dynamically:
this["spanish"+"Language"]
In AS3 it's not possible to write something like:
Controller.this["spanish"+"Language"]
Is there any way to achieve this? Although everything is working I want to be able to keep my code as minimal as possible.
It is possible to access public static properties of a class this way (assuming the class name is Controller as in your example:
Controller['propertyName']
I'm not sure how this helps to have "minimal code", but this would be a different topic/question, which might need some more details on what you want to achive.
Having said that, I like the approach DodgerThud suggests in the comments of grouping similar values in a (dynamic) Object or Dictonary and give it a proper name.
Keep in mind, that if the string you pass in as the key to the class or dynamic object is created from (textual) user input you should have some checks for the validity of that data, otherwise your programm might crash or expose other fields to the user.
It would make sense to utilize a Dictionary object for a set of variables inherited: it provides a solid logic and it happens to work...
I do not think this is what you are trying to accomplish. I may be wrong.
Classes in AS3 are always wrapped within a package - this is true whether you have compiled from Flash, Flex, Air, or any other...
Don't let Adobe confuse you. This was only done in AS3 to use Java-Based conventions. Regardless, a loosely typed language is often misunderstood, unfortunately. So:
this["SuperObject"]["SubObject"]["ObjectsMethod"][ObjectsMethodsVariable"](args..);
... is technically reliable because the compiler avoids dot notation but at runtime it will collect a lot of unnecessary data to maintain those types of calls.
If efficiency becomes an issue..
Use:
package packages {
import flash.*.*:
class This implements ISpecialInterface {
// Data Objects and Function Model
// for This Class
}
package packages {
import...
class ISpecialInterface extends IEventDispatcher
I have an ASP.NET 3.5 web application project in which I'm trying to implement a searchable gridview. I originally started the project as a web site and converted it to a web application. After conversion, my class ended up in the folder Old_App_Code and is called SearchGridView.vb.
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Drawing.Design
<Assembly: TagPrefix("MyApp.WebControls", "SearchGridView")>
Namespace MyApp.WebControls
#Region "TemplateColumn"
Public Class NumberColumn
Implements ITemplate
Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
End Sub
End Class
#End Region
<ToolboxData("<{0}:SearchGridView runat=server></{0}:SearchGridView>")> _
<ParseChildren(True, "SearchFilters")> _
Public Class SearchGridView
Inherits GridView
The class file continues, but this is the first part of it.
Unfortunately, I receive the error message
Warning 1 Namespace or type specified in the project-level Imports 'MyApp.WebControls' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases. DielWebProj
In web.config, I included a namespace tag for MyApp.WebControls and I included an imports tag in the .aspx page as well.
Can anyone shed light as to why this error is being raised and how I would remedy it?
Thanks,
Sid
I have a broadly similar problem to you. I have a website project using a custom control, inheriting from GriView, in the app_code folder. I was recieving the very same error, but noted that it happened only after I would add a second class or module to app_code, and would disappear if I removed it.
So the workaround I have at the moment is to just leave my custom control as the sole occupant of app_code.
One option might be to make the control part of its own project and add it as a reference to the we site/app?
I'll update this if I can find a decent solution.
EDIT:
Well, in my case it was because the control I was using was written in C#, whereas the rest of the project, and classes I added to app_code, were in VB.
The app_code folder is compiled to a single assembly, so classes of different languages cannot share it, unless you create seperate sub-folders and do some config file jiggerypokery. More details here