Dart abstract private method - dart

How can I have an abstract private method in dart?
// person.dart
abstract class Person{
void _walk(); //Abstract Method
void _talk(); //Abstract Method
}
// jay.dart
import "person.dart";
class Jay extends Person{
#override
void _walk() {
print("Jay can walk");
}
#override
void _talk() {
print("Jay can talk");
}
}
I want to hide _walk and _talk from Jay instance

package:meta provides a #visibleForOverriding annotation that might do what you want. Note that violating it will generate only an analysis warning, and it won't be enforced at runtime.
Personally I think that putting things that are meant to be private in the abstract base class is a bad idea since they shouldn't be part of the interface. Consider instead doing:
abstract class Person {
...
}
abstract class _Person extends Person {
void walk();
void talk();
}
and now your library can internally derive classes from _Person and use walk and talk, and they won't be exposed at all to external consumers of your library.

Related

Dart cannot override function in generic class with subclass of generic

I am writing an app which deals with both cryptos and stocks. Because they share many common characteristics such as symbol, price, name etc, I created a base class 'instrument' then subclasses for stock and crypto. I have a generic 'manager' class for both, as loading, saving etc are again very similar. However, there are some functions, such as fetching a current price, that need to be implemented differently, so I have extended my generic manager class and I am trying to override the relevant function, i.e. fetchCurrentPrice() in the example below. Dart complains that
'CryptoManager.fetchCurrentPrice' ('Future Function(Crypto)') isn't a valid override of 'Manager.fetchCurrentPrice' ('Future Function(Instrument)').
I don't understand this, as I have defined as type in the manager, and Crypto extends Instrument, so I am fulfilling this criterion. Any idea where I am going wrong?
abstract class Instrument {
String name = 'Instrument';
double currentPrice = 0.0;
Instrument(this.name);
}
class Crypto extends Instrument {
Crypto(super.name);
String contractAddress = '0xBCCFF3FF6...';
}
abstract class Manager<T extends Instrument> {
List<T> instruments = [];
Future<double> fetchCurrentPrice(T instrument) async {
print('Fetching price for generic instrument');
return 12.80;
}
}
class CryptoManager extends Manager {
// this is causing the issue
#override
Future<double> fetchCurrentPrice(Crypto instrument) async {
print('Fetching price for crypto');
return 12.80;
}
}
void main(List<String> args) {
CryptoManager cryptoManager = CryptoManager();
var btcCrypto = Crypto('BTC');
cryptoManager.fetchCurrentPrice(btcCrypto);
}
Your class CryptoManager needs to extend Manager<Crypto>, not just "some Manager, kinda".
class CryptoManager extends Manager<Crypto>

In Dart, it is not possible to override a static method. but i can't understand output of this code

class Student {
static void getDetails() {
print('Get details method of Student class');
}
}
class DartStudent extends Student {
static void getDetails() {
print('Get details method of DartStudent class');
}
}
void main() {
DartStudent.getDetails();
}
Output : Get details method of DartStudent class
Expected : Error. static method cannot be overriden.. or something wrong..
what's wrong with me?
getDetails() in DartStudent class is not overriding parent class's method?
You can't override static methods.
The two static methods you declared there are in fact two different static methods, not the same, overriden one.
Answer for a different question, but related:
Dart doesn't inherit static methods to derived classes. So it makes no sense to create abstract static methods (without implementation).
Also check out Why shouldn't static methods be able to be overrideable?. It provides a thorough explanation of why static methods should not be overrideable in general.

Dart forcing me to implement non abstract method in child class

I am trying abstract classes I found one issue that I have to implement the non-abstract method having a body in child classes
code:
abstract class Animal{
void breathe(); //abstract method
void makeNoise(){
//non abstract method
print('making animal noises!');
}
}
abstract class IsFunny{
void makePeopleLaugh();//abstract method
}
class TVShow implements IsFunny{
String name;
#override
void makePeopleLaugh() {
// TODO: implement makePeopleLaugh
print("TV show is funny and make people laugh");
}
}
class Comedian extends Person implements IsFunny{
Comedian(String name, String nation) : super(name, nation);
#override
void makePeopleLaugh() {
// TODO: implement makePeopleLaugh
print('make people laugh');
}
}
class Person implements Animal{
String name,nation;
Person(this.name,this.nation);
//we must implement all the methods present in Abstract class and child should override the abstract methods
#override
void breathe() {
// TODO: implement breathe
print('person breathing through nostrils!');
}
//there should be no compulsion to override non abstract method
#override
void makeNoise() {
// TODO: implement makeNoise
print('shouting!');
}
}
void main(List arguments) {
var swapnil=new Person('swapnil','India');
swapnil.makeNoise();
swapnil.breathe();
print('${swapnil.name},${swapnil.nation}');
}
here I am trying not to implement makeNoise method in my Person class but it gives error and says abstract method must be implemented.
Is this bug or I am getting concept wrong
You are using implements, which is used for interfaces, not for inheritance. The keyword you are looking for is extends.
abstract class Foo {
void doThing() {
print("I did a thing");
}
void doAnotherThing();
}
class Bar extends Foo {
#override
void doAnotherThing() {
print("I did another thing");
}
}
I don't believe this is a bug. The method is still in an abstract class that you are implementing. I think that you instead intended to extend the class in which case you would call super.makeNoise() in the override.
I figured out the solution after some time I understood that when inheriting abstract class I should have used extends keyword instead of implements due to which dart was telling me to also implement the non-abstract method as it is compulsory to implement all methods when using interfaces.
I think my question was silly

How to inject a list with different implementations of the same interface in a nested module scenario via Guice?

There is an interface DCE, which is implemented by a class DCEImpl which has a dependency, say, string S, which it gets via its constructor.
The universe of S is limited, say S can only take values {'A','B','C'}.
There is an already existing Guice module that accepts the value of S in its constructor, and then binds the interface DCE to the correctly initialized version of DCEImpl.
public class DCEModule extends AbstractModule {
private final String s;
public DCEModule(String s){
this.s = s;
}
protected void configure() {
bind(DCE.class).toInstance(new DCEImpl(s));
}
}
Now I have a class C which needs a List<DCE> with all the 3 implementations (actually a lot more than 3, using 3 for example purpose).
I want to inject this list via Guice in C. To do that, I created a new module DCEPModule, which will provide a List<DCE> in this way:
#Provides
List<DCE> getDCE() {
for(String s: S){
Module m = new DCEModule(s);
install(m);
Injector injector = Guice.createInjector(m);
listDomains.add(injector.getInstance(DCE.class));
}
}
My problem is that I don't want to call a new injector in this module, because DCEPModule will be installed by a different module.
public class NewModule extends AbstractModule {
protected void configure() {
install(DCEPModule);
}
}
I want a way to get the List<DCE> without explicitly creating a new injector in DCEPModule.
You can achieve this by using a Multibinder (javadoc, wiki).
Here’s an example:
public class SnacksModule extends AbstractModule {
protected void configure(){
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
  multibinder.addBinding().toProvider(SnickersProvider.class);
  multibinder.addBinding().to(Skittles.class);
}
}
Now, the multibinder will provide a Set<Snack>. If you absolutely need a List instead of a Set, then you can add a method to your module like this:
#Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
return new ArrayList(snackSet);
}
You can add implementations to the same Multibinding in more than one module. When you call Multibinder.newSetBinder(binder, type) it doesn’t necessarily create a new Multibinding. If a Multibinding already exists for for that type, then you will get the existing Multibinding.

Use Guice nested injects

I'm relatively new to Guice, and some things still give me a pretty hard time.
My particular question is, how do you handle nested injections in Guice.
Example:
Class A uses Class B via #Inject, and Class B uses Class C.
Explicitly:
My Module where I bind to Providers.
public class ModuleBinder extends AbstractModule {
#Override
protected void configure() {
bind(DatabaseControllerInterface.class)
.toProvider(DatabaseControllerProvider.class).asEagerSingleton();
bind(AnalyzerInterface.class)
.toProvider(AnalyzerProvider.class).asEagerSingleton();
bind(SystemAdministrationInterface.class)
.toProvider(SystemAdministrationProvider.class).asEagerSingleton();
bind(LogInServiceInterface.class)
.toProvider(LogInServiceProvider.class);
}
}
The DatabaseControllerProvider:
public class DatabaseControllerProvider implements Provider<DatabaseControllerInterface> {
#Override
public DatabaseControllerInterface get() {
return new DatabaseControllerImpl();
}
}
The LogInServiceProvider:
public class LogInServiceProvider implements Provider<LogInServiceInterface> {
#Override
public LogInServiceInterface get() {
return new LogInServiceImpl();
}
}
And finally, the LogInService uses:
public class LogInServiceImpl implements LogInServiceInterface{
#Inject
private DatabaseControllerProvider databaseControllerProvider;
private final DatabaseControllerInterface databaseController;
public LogInServiceImpl() {
this.databaseController = databaseControllerProvider.get();
}
#Override
public User register(final String mail, final String userName, final String password) {
databaseController.registerUser(userName, mail, password, UserRole.ADMIN);
}
}
The call is then:
public class Test() {
public static test() {
final Injector injector = Guice.createInjector(new ModuleBinder());
logInService = injector.getInstance(LogInServiceInterface.class);
logInService.registerUser("test", "test", "test");
}
}
I know most of you guys will get sick with that code, but hey, I'm a beginner with Guice, so please be gentle with me.
I want to use Constructor injection, I already realized that field injection is considered "evil". Do you have any idea how to get that working by keeping the providers (I need them)?
Using the injections in the example does nothing on the "second" level, the DatabaseControllerImpl in LogInServiceImpl is null.
Did I configure something wrong? Did I misunderstand the usage of Provides and/or Modules?
I hope somebody can and wants to help me. If you need more informations, post a comment.
With best regards,
JosefRucksack
Your direct answer: You're calling new T(); in your Providers, which doesn't support field injection.
First, a real timesaver: Don't keep your explicit Providers. If you have bound a T, Guice allows you to inject a Provider or call Injector.getProvider for that T, even if you haven't explicitly created a Provider yourself. See the Built-In Bindings page on the wiki,
or the Injector docs (emphasis mine):
Contains several default bindings:
This Injector instance itself
A Provider<T> for each binding of type T
The Logger for the class being injected
The Stage in which the Injector was created
Instead, do it this way:
public class ModuleBinder extends AbstractModule {
#Override
protected void configure() {
bind(DatabaseControllerInterface.class)
.to(DatabaseControllerImpl.class).asEagerSingleton();
bind(AnalyzerInterface.class)
.to(AnalyzerImpl.class).asEagerSingleton();
bind(SystemAdministrationInterface.class)
.to(SystemAdministrationImpl.class).asEagerSingleton();
bind(LogInServiceInterface.class)
.to(LogInServiceImpl.class);
}
}
You then have the same choice you do now, to inject T or Provider<T> and call getInstance or getProvider as needed.
If your Providers are absolutely necessary, especially if they actually receive an instance from some other system or service locator, one other option is to add your #Inject fields into them as in the Provider bindings wiki page and pass them into your constructor, or to just inject a MembersInjector<T>:
public class LogInServiceProvider implements Provider<LogInServiceInterface> {
#Inject MembersInjector<LogInServiceImpl> logInServiceImplInjector;
#Override
public LogInServiceInterface get() {
LogInServiceImpl logInServiceImpl = YourExternalDep.getLogInService();
logInServiceImplInjector.injectMembers(logInServiceImpl);
return logInServiceImpl;
}
}
However, this explicit-Provider solution is not idiomatic Guice, and should only be used with external or legacy code. Guice's whole reason for existence is to automate away boilerplate and let your systems come together clearly and flexibly. Providers are an implementation detail; let Guice create them for you.

Resources