Set the case there are multiple libraries of a package which need access to a commonly used class which is in its own library. This class gets exported and contains private fields which should only be accessible internally by libraries of the package. Because the part of directive is discouraged I am avoiding it. So this is the challenge: How can I access private fields of a public class from another library of the same package without using part of?
This is what a came up with:
class PublicClass {
Object _shouldNotBePublic;
}
class InternalClass extends PublicClass {
Object get publicInternally => _shouldNotBePublic;
}
And it partially solves the problem.
But now there is an exported function
void someFunction(PublicClass param) {
param._shouldNotBePublic;
}
which takes an argument of PublicClass and it needs to access the private _shouldNotBePublic field. That is exactly what C++ friend does. Are there any good solutions for Dart that don't involve part of?
Edit: The workaround I use for the time being is a simple not exported function in the same library like PublicClass:
Object getShouldNotBePublic(PublicClass obj) {
return obj._shouldNotBePublic
}
Related
I'm trying to create a static extension method on one of my classes (which is autogenerated, so I can't easily modify it). According to the docs, this should be possible:
Extensions can also have static fields and static helper methods.
Yet even this small example does not compile:
extension Foo on String {
static String foo() => 'foo!';
}
void main() {
print(String.foo());
}
Error: Method not found: 'String.foo'.
print(String.foo());
^^^
What am I doing wrong?
The docs mean that the extension classes themselves can have static fields and helper methods. These won't be extensions on the extended class. That is, in your example, Foo.foo() is legal but String.foo() is not.
You currently cannot create extension methods that are static. See https://github.com/dart-lang/language/issues/723.
Note that you also might see Dart extension methods referred to as "static extension methods", but "static" there means that the extensions are applied statically (i.e., based on the object's type known at compilation-time, not its runtime type).
As James mentioned, you can't use the static method directly on the extended class as of today, the current solution to your problem would be:
extension Foo on String {
String foo() => 'foo!';
}
void main() {
print('Hi'.foo());
}
I have a class that extends another. The parent class is not intended to be used directly by the API rather it implements basic methods that are helpers for child classes.
When I use the child class in a program I can see all method from said class but also the one from the parent class that are not intended to be called directly, they exist to be called by the methods of the child class.
I tried to make parents method private. This would work I believe as long as parent and child are declared in the same library. But I have an issue with the "library" notion. I understand part/part of are somewhat depreciated, and I want the parent class to be in a specific file. I can't figure a way to do it with import/export.
Is there a way to either hide a public method from the parent class from all child classes usage or to make a private method from the parent class callable from all child classes ?
Best regards ;
Exemple:
myLib.dart
export mainClass.dart;
mainClass.dar
import baseClass.dart;
class MainClass extends BaseClass {
publicFunc() => ... //Can't call _hiddenFunc, can call wantToHideFunc()
}
In a second file (for code reusability purposes)
class MainClass extends BaseClass {
_hiddenFunc() => ...
wantToHideFunc() => ...
}
Using myLib public API
import myLib.dart
main() {
class = Class();
class.publicFunc(); //Intended
class.wantToHideFunc() //Wants to avoid...
}
Dart does not have protected access like Java or C#.
You can't hide a public member, you can't access a private member from a different library, and there is no third option.
It sounds like you want members of the superclass which can be invoked only from subclasses, not from outside of the object. That's what's called protected in, e.g., Java, and Dart does not have anything similar to that.
The only level of privacy in Dart is library-private, which is chosen by starting the name with a _.
The reason that Dart has this design is that it was originally a very dynamic language. You can preform "dynamic invocations" on a value with static type dynamic, say dynVal.foo(42) and it will call the method of that name.
To make a name unreachable, it needed to be safe from dynamic invocation as well. Because of that, Dart privacy does not care where the code doing the invocation is, it only cares whether you know the name - and library private names are considered different names depending on which library they're from.
Using part is not discouraged for situations where it actually serves a purpose. If you can put the part into a library of its own, that's better because it allows it to have its own privacy and imports, but if you need the classes to share privacy, using part files to split up a large file is perfectly reasonable. It's a tool, there is nothing wrong with using it when it's the right tool for the job. A library is often a better tool for modularity, but not always.
Now, there is a hack you can use:
// Declare the base and provide extensions for "protected" members:
abstract class Base {
int get _someHiddenStuff => 42;
int get somePublicStuff => 37;
}
extension ProtectedBase on Base {
int get someHiddenStuff => _someHiddenStuff;
}
Then import that in another library and do:
import "base.dart";
export "base.dart" hide ProtectedBase;
class SubClass extends Base {
int doSomething => someHiddenStuff + somePublicStuff;
}
Then anyone importing "subclass.dart" will also get a version of Base, but they won't get the ProtectedBase extensions. Hiding the extensions from your package's public API will allow yourself to use it, but prevent your package's users from seeing the helper extensions.
(This is likely highly over-engineered, but it's an option. It's the evolution of the hack of having static/top-level helper functions that you don't export.)
I would like to use JS interop to expose a set of functions/objects coded in dart.
I know how to use js-interop to share variables with JS scripts. But I have a requirement : I can't edit dart classes as they are coming from an external library without JS dependency.
And while I know it's possible to do something like :
#anonymous
#JS()
class Config {
external bool get value;
external factory Config({bool value});
factory Config.fromExternalLib(ExternalConfig config) {
return new Config(value: config.value);
}
}
I'd like to avoid that, as it requires to duplicate every classes.
Is there any way to convert any dart object to JS object without modifying or forking the class ?
Here's the situation: I have an abstract class with a constructor that takes a boolean (which controls some caching behavior):
abstract class BaseFoo { protected BaseFoo(boolean cache) {...} }
The implementations are all generated source code (many dozens of them). I want to create bindings for all of them automatically, i.e. without explicit hand-coding for each type being bound. I want the injection sites to be able to specify either caching or non-caching (true/false ctor param). For example I might have two injections like:
DependsOnSomeFoos(#Inject #NonCaching AFoo aFoo, #Inject #Caching BFoo bFoo) {...}
(Arguably that's a bad thing to do, since the decision to cache or not might better be in a module. But it seems useful given what I'm working with.)
The question then is: what's the best way to configure bindings to produce a set of generated types in a uniform way, that supports a binding annotation as well as constructor param on the concrete class?
Previously I just had a default constructor on the implementation classes, and simply put an #ImplementedBy on each of the generated interfaces. E.g.:
// This is all generated source...
#ImplementedBy(AFooImpl.class)
interface AFoo { ... }
class AFooImpl extends BaseFoo implements AFoo { AFooImpl() { super(true); } }
But, now I want to allow individual injection points to decide if true or false is passed to BaseFoo, instead of it always defaulting to true. I tried to set up an injection listener to (sneakily) change the true/false value post-construction, but I couldn't see how to "listen" for a range of types injected with a certain annotation.
The problem I keep coming back to is that bindings need to be for a specific type, but I don't want to enumerate all my types centrally.
I also considered:
Writing some kind of scanner to discover all the generated classes and add a pair of bindings for each of them, perhaps using Google Reflections.
Creating additional, trivial "non caching" types (e.g. AFoo.NoCache extends AFoo), which would allow me to go back to #ImplementedBy.
Hard wiring each specific type as either caching/non-caching when it's generated.
I'm not feeling great about any of those ideas. Is there a better way?
UPDATE: Thanks for the comment and answer. I think generating a small module alongside each type and writing out a list of the modules to pull in at runtime via getResources is the winner.
That said, after talking w/ a coworker, we might just dodge the question as I posed it and instead inject a strategy object with a method like boolean shouldCache(Class<? extends BaseFoo> c) into each generated class. The strategy can be implemented on top of the application config and would provide coarse and fine grained control. This gives up on the requirement to vary the behavior by injection site. On the plus side, we don't need the extra modules.
There are two additional approaches to look at (in addition to what you mentioned):
Inject Factory classes instead of your real class; that is, your hand-coded stuff would end up saying:
#Inject
DependsOnSomeFoos(AFoo.Factory aFooFactory, BFoo.Factory bFooFactory) {
AFoo aFoo = aFooFactory.caching();
BFoo bFoo = bFooFactory.nonCaching();
...
}
and your generated code would say:
// In AFoo.java
interface AFoo {
#ImplementedBy(AFooImpl.Factory.class)
interface Factory extends FooFactory<AFoo> {}
// ...
}
// In AFooImpl.java
class AFooImpl extends BaseFoo implements AFoo {
AFooImpl(boolean caching, StuffNeededByAFIConstructor otherStuff) {
super(caching);
// use otherStuff
}
// ...
class Factory implements AFoo.Factory {
#Inject Provider<StuffNeededByAFIConstructor> provider;
public AFoo caching() {
return new AFooImpl(true, provider.get());
}
// ...
}
}
Of course this depends on an interface FooFactory:
interface FooFactory<T> {
T caching();
T nonCaching();
}
Modify the process that does your code generation to generate also a Guice module that you then use in your application setup. I don't know how your code generation is currently structured, but if you have some way of knowing the full set of classes at code generation time you can either do this directly or append to some file that can then be loaded with ClassLoader.getResources as part of a Guice module that autodiscovers what classes to bind.
What is the difference between early and late binding?
The short answer is that early (or static) binding refers to compile time binding and late (or dynamic) binding refers to runtime binding (for example when you use reflection).
In compiled languages, the difference is stark.
Java:
//early binding:
public create_a_foo(*args) {
return new Foo(args)
}
my_foo = create_a_foo();
//late binding:
public create_something(Class klass, *args) {
klass.new_instance(args)
}
my_foo = create_something(Foo);
In the first example, the compiler can do all sorts of neat stuff at compile time. In the second, you just have to hope that whoever uses the method does so responsibly. (Of course, newer JVMs support the Class<? extends Foo> klass structure, which can greatly reduce this risk.)
Another benefit is that IDEs can hotlink to the class definition, since it's declared right there in the method. The call to create_something(Foo) might be very far from the method definition, and if you're looking at the method definition, it might be nice to see the implementation.
The major advantage of late binding is that it makes things like inversion-of-control easier, as well as certain other uses of polymorphism and duck-typing (if your language supports such things).
Similar but more detailed answer from Herbert Schildt C++ book:-
Early binding refers to events that occur at compile time. In essence, early binding occurs when all information needed to call a function is known at compile time. (Put differently, early binding means that an object and a function call are bound during compilation.) Examples of early binding include normal function calls (including standard library functions), overloaded function calls, and overloaded operators. The main advantage to early binding is efficiency. Because all information necessary to call a function is determined at compile time, these types of function calls are very fast.
The opposite of early binding is late binding. Late binding refers
to function calls that are not resolved until run time. Virtual functions are used to achieve late binding. As you know, when access is via a base pointer or reference, the virtual function actually called is determined by the type of object pointed to by the pointer. Because in most cases this cannot be determined at compile time, the object and the function are not linked until run time. The main advantage to late binding is flexibility. Unlike early binding, late binding allows you to create programs that can respond to events occurring while the program executes without having to create a
large amount of "contingency code." Keep in mind that because a function call is not resolved until run time, late binding can make for somewhat slower execution times.
However today, fast computers have significantly reduced the execution times related to late binding.
Taken directly from http://word.mvps.org/fAQs/InterDev/EarlyvsLateBinding.htm
There are two ways to use Automation (or OLE Automation) to
programmatically control another application.
Late binding uses CreateObject to create and instance of the
application object, which you can then control. For example, to create
a new instance of Excel using late binding:
Dim oXL As Object
Set oXL = CreateObject("Excel.Application")
On the other hand, to manipulate an existing instance of Excel (if
Excel is already open) you would use GetObject (regardless whether
you're using early or late binding):
Dim oXL As Object
Set oXL = GetObject(, "Excel.Application")
To use early binding, you first need to set a reference in your
project to the application you want to manipulate. In the VB Editor of
any Office application, or in VB itself, you do this by selecting
Tools + References, and selecting the application you want from the
list (e.g. “Microsoft Excel 8.0 Object Library”).
To create a new instance of Excel using early binding:
Dim oXL As Excel.Application
Set oXL = New Excel.Application
In either case, incidentally, you can first try to get an existing
instance of Excel, and if that returns an error, you can create a new
instance in your error handler.
In interpreted languages, the difference is a little more subtle.
Ruby:
# early binding:
def create_a_foo(*args)
Foo.new(*args)
end
my_foo = create_a_foo
# late binding:
def create_something(klass, *args)
klass.new(*args)
end
my_foo = create_something(Foo)
Because Ruby is (generally) not compiled, there isn't a compiler to do the nifty up-front stuff. The growth of JRuby means that more Ruby is compiled these days, though, making it act more like Java, above.
The issue with IDEs still stands: a platform like Eclipse can look up class definitions if you hard-code them, but cannot if you leave them up to the caller.
Inversion-of-control is not terribly popular in Ruby, probably because of its extreme runtime flexibility, but Rails makes great use of late binding to reduce the amount of configuration necessary to get your application going.
public class child()
{ public void method1()
{ System.out.println("child1");
}
public void method2()
{ System.out.println("child2");
}
}
public class teenager extends child()
{ public void method3()
{ System.out.println("teenager3");
}
}
public class adult extends teenager()
{
public void method1()
{ System.out.println("adult1);
super.method1();
}
}
//In java
public static void main(String []args)
{ ((teenager)var).method1();
}
This will print out
adult1
child1
In early binding the compiler will have access to all of the methods
in child and teenager
but in late binding (at runtime), it will check for methods that are overridden
at runtime.
Hence method1(from child -- early binding) will be overridden by the method1 from adult at runtime(late binding)
Then it will implement method1 from child since there is no method1 in method1 in teenager.
Note that if child did not have a method1 then the code in the main would not compile.
The compile time polymorphism also called as the overloading or early binding or static binding when we have the same method name with different behaviors. By implementing the multiple prototype of the same method and different behavior occurs in it. Early binding refers first compilation of the program .
But in late binding object is runtime occurs in program. Also called as Dynamic binding or overriding or Runtime polymorphism.
The easiest example in java:
Early (static or overloading) binding:
public class Duck {
public static void quack(){
System.out.println("Quack");
}
}
public class RubberDuck extends Duck {
public static void quack(){
System.out.println("Piiiiiiiiii");
}
}
public class EarlyTest {
public static void main(String[] args) {
Duck duck = new Duck();
Duck rubberduck = new RubberDuck();
duck.quack();
rubberduck.quack(); //early binding - compile time
}
}
Result is:
Quack
Quack
while for Late (dynamic or overriding) binding:
public class Duck {
public void quack(){
System.out.println("Quack");
}
}
public class RubberDuck extends Duck {
public void quack(){
System.out.println("Piiiiiiiiii");
}
}
public class LateTest {
public static void main(String[] args){
Duck duck = new Duck();
Duck rubberduck = new RubberDuck();
duck.quack();
rubberduck.quack(); //late binding - runtime
}
}
result is:
Quack
Piiiiiiiiii
Early binding happens in compile time, while late binding during runtime.