Using Generic swift enum in a protocol - objective-c

I have case where I often scratch my head around, let's say I have a generic Manager class in a pod that can handle permission, and within the app, I want to be able to extend it to create more meaningful method name, aka to use with enum as parameter, to make its use more clear and less prone to mistake.
But it seems that you can't call private method when you create the extension elsewhere.
I'm sure there would be a more clean way with Generic/AssociatedValue or maybe my pattern is just wrong...
Here's the simplified version of it:
Class in the external pod:
public class FeatureDataManager {
public static let shared = FeatureDataManager()
private var permissionManager: PermissionManager!
private init() {
self.permissionManager = PermissionManager()
}
private getPermission(forFeature feature: String) -> Bool {
return self.permissionManager.isEnable(feature)
}
}
and the extension in the app:
extension FeatureDataManager {
enum FeatureType: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
public func isPermissionEnable(forFeature feature: FeatureType) {
// Does not compile, visibility issue
self.getPermission(forFeature: feature.rawValue)
}
}
Clarification:
FeatureDataManager is a class in the Pod that is solely used to check for permissions in the form of String value across many app that are using importing it.
I wanted each single app using it, to define an extension that would have their own finite enum of their supported permissions. Let's say App A support Ads, but not App B. So I wanted to have a universal method that when you call featureManager.isPermissionEnable(.Ads), whenever app that is, the auto-complete would just offer the list of the supported permission for that app. Also, the goal of wrapping my string permission value into an enum is to be more bulletproof to mistake and easier refactoring if a name change, just have to change it in a single place.

What you're looking for would be a "protected" level, and that doesn't exist in Swift, and can't exist without creating a new protection level, since it would break compiler optimizations. In your example, since getPermission(forFeature:) is promised never to be called outside this scope, the compiler is free to inline it. So this function may not even exist at the point that your extension wants to call it.
It would be possible for Swift to add a "protected" level that is "semi-public," but Swift does not have any such feature. You will need to redesign FeatureDataManager to make this possible. From your example, it's not obvious how to do that, because you provide no public interface for permissions at all, so it's not clear what you mean by "I want to be able to extend it to create more meaningful method name." Currently there is no public method name. If there were one, then making a more convenient syntax like you describe would be easy.
Can you give an example of the calling code that you want this extension to improve?
For more on why the language is this way, see Access Control and protected. It's not an accident.
You note that you can do this in the same file, and that's true. Swift allows this for stylistic reasons (many people use extensions inside a single file for code organization reasons). Swift treats all extensions in the same file as being in the main definition. But that does not extend to other files, and certainly not to other modules.
The generic solution to this looks like:
public class FeatureDataManager<Feature>
where Feature: RawRepresentable, Feature.RawValue == String {
private func getPermission(forFeature feature: String) -> Bool { ... }
public func isPermissionEnable(forFeature feature: Feature) {
self.getPermission(forFeature: feature.rawValue)
}
}
An App would then create a feature set and create a manager for that feature set:
enum AppFeature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
let featureDataManager = FeatureDataManager<AppFeature>()
featureDataManager.isPermissionEnable(forFeature: .ads)
That does prevent the easy creation of a .shared instance. It's arguable whether that's good or bad, but on the assumption that you want it, you would need to wrap it up:
class AppFeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
static var shared = AppFeatureDataManager()
let manager = FeatureDataManager<Feature>()
public func isPermissionEnable(forFeature feature: Feature) {
manager.isPermissionEnable(forFeature: feature)
}
}
Now that's a bit too much boiler-plate for the app side (especially if there are more methods than isPermissionEnable), so you can remove the boilerplate this way (full code):
public class FeatureDataManager<Feature>
where Feature: RawRepresentable, Feature.RawValue == String {
private var permissionManager: PermissionManager
init() {
self.permissionManager = PermissionManager()
}
private func getPermission(forFeature feature: String) -> Bool {
self.permissionManager.isEnable(feature)
}
public func isPermissionEnable(forFeature feature: Feature) {
self.getPermission(forFeature: feature.rawValue)
}
}
protocol AppFeatureDataManager {
associatedtype Feature: RawRepresentable where Feature.RawValue == String
var manager: FeatureDataManager<Feature> { get }
}
// Here you can write any necessary pass-through functions so the app doesn't have to
extension AppFeatureDataManager {
public func isPermissionEnable(forFeature feature: Feature) {
manager.isPermissionEnable(forFeature: feature)
}
}
//
// Application Developer writes this:
//
class MyGreatAppFeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
// This is the only thing that's really required
let manager = FeatureDataManager<Feature>()
// They're free make this a shared instance or not as they like.
// That's not something the framework cares about.
static var shared = MyGreatAppFeatureDataManager()
private init() {}
}
All that said, I think this is getting too many layers if FeatureDataManager is really just a front-end for PermissionManager like you've described here. (Maybe your example is highly simplified, so the below doesn't apply.)
If PermissionManager is public, and the real goal is just to have a nicer front-end to it, I would write it this way:
protocol FeatureDataManager {
associatedtype Feature: RawRepresentable where Feature.RawValue == String
var permissionManager: PermissionManager { get }
}
extension FeatureDataManager {
func isPermissionEnable(forFeature feature: Feature) {
permissionManager.isEnable(feature.rawValue)
}
}
//
// App developer writes this
//
class MyGreatAppFeatureDataManager: FeatureDataManager {
enum Feature: String {
case ads = "ads"
case showBanner = "banner"
case showFullScreenPub = "showFullScreenPub"
}
// This is the only required boilerplate; the protocol can't do this for you.
let permissionManager = PermissionManager()
// And the developer can decide to make it a shared instance if they like,
// but it's not the business of the framework
static let shared = MyGreatAppFeatureDataManager()
private init() {}
}

The private access control restricts the use of an entity :
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file.
Access Control - The Swift Programming Language
If you want an entity accessible through class extension (in another file and in the same module/package) : use internal access control.
If you want an entity accessible through class extension (in another file and in another module/package) : use public access control.

You have to declare fileprivate access level to access it in an extension defined in same file. You cannot access private entities out of its defined scope, even if extension relies on same file!

Related

What's the use for Kotlin's #JvmSynthetic on a file target?

The #JvmSynthetic annotation is allowed to be used on a file, but I can't figure out what the purpose of this would be.
I was hoping I could hide a file containing a bunch of Kotlin-only extension methods from Java users, but that doesn't seem to be the case:
// Extensions.kt
#file:JvmSynthetic
#JvmSynthetic
fun Foo.mySyntheticExtension() = ...
fun Foo.myExtension() = ...
// Java usage
// This doesn't compile (as expected)
Extensions.mySyntheticExtension(foo);
// This compiles fine, so #JvmSynthetic on a file does not trickle down to all its functions
Extensions.myExtension(foo);
Even without the non-synthetic method Java users still see the cluttering ExtensionsKt class, although it appears empty to them.
If #file:JvmSynthetic doesn't hide the file('s generated class) from Java, nor trickles down the synthetic status to all functions in it, what is its intended purpose?
The original proposal that caused this annotation target to be added was KT-41884:
The rationale given was:
This would apply to the synthesized class which encapsulates top-level members. This allows hiding those members from Java when they are internal visibility.
For example:
// ManyInternals.kt, in module A
#file:JvmSynthetic
internal fun foo() {
}
internal fun bar() {
}
// Main.java, in module B
public class Main {
public static void main(String[] args) {
ManyInternalsKt.foo(); // error
}
}

How best to return a single value of different types from function

I have a function that returns either an error message (String) or a Firestore DocumentReference. I was planning to use a class containing both and testing if the error message is non-null to detect an error and if not then the reference is valid. I thought that was far too verbose however, and then thought it may be neater to return a var. Returning a var is not allowed however. Therefore I return a dynamic and test if result is String to detect an error.
IE.
dynamic varResult = insertDoc(_sCollection,
dataRec.toJson());
if (varResult is String) {
Then after checking for compliance, I read the following from one of the gurus:
"It is bad style to explicitly mark a function as returning Dynamic (or var, or Any or whatever you choose to call it). It is very rare that you need to be aware of it (only when instantiating a generic with multiple type arguments where some are known and some are not)."
I'm quite happy using dynamic for the return value if that is appropriate, but generally I try to comply with best practice. I am also very aware of bloated software and I go to extremes to avoid it. That is why I didn't want to use a Class for the return value.
What is the best way to handle the above situation where the return type could be a String or alternatively some other object, in this case a Firestore DocumentReference (emphasis on very compact code)?
One option would be to create an abstract state class. Something like this:
abstract class DocumentInsertionState {
const DocumentInsertionState();
}
class DocumentInsertionError extends DocumentInsertionState {
final String message;
const DocumentInsertionError(this.message);
}
class DocumentInsertionSuccess<T> extends DocumentInsertionState {
final T object;
const DocumentInsertionSuccess(this.object);
}
class Test {
void doSomething() {
final state = insertDoc();
if (state is DocumentInsertionError) {
}
}
DocumentInsertionState insertDoc() {
try {
return DocumentInsertionSuccess("It worked");
} catch (e) {
return DocumentInsertionError(e.toString());
}
}
}
Full example here: https://github.com/ReactiveX/rxdart/tree/master/example/flutter/github_search

How to find all classes in a package using reflection in kotlin

Is it possible to find all kotlin classes in a given package?
I also need only annotated classes but it's not a big deal. Any suggestions ?
Kotlin on the JVM suffers the same issue as Java in this regard due to the implementation of class loaders.
Class loaders are not required to tell the VM which classes it can provide, instead they are just handed requests for classes, and have to return a class or throw an exception.
Source and more information: Can you find all classes in a package using reflection?
To summarize the linked thread, there are a number of solutions that allow you to inspect your current class path.
The Reflections library is pretty straight forward and has a lot of additional functionality like getting all subtypes of a class, get all types/members annotated with some annotation, optionally with annotation parameters matching, etc.
Guava has ClassPath, which returns ClassInfo POJO's - not enough for your use case, but useful to know as Guava is available almost everywhere.
Write your own by querying classloader resources and code sources. Would not suggest this route unless you absolutely cannot add library dependencies.
Here's an example of querying classloader resources, adapted from https://www.javaworld.com/article/2077477/java-tip-113--identify-subclasses-at-runtime.html
Requires Java 8 or higher.
// Call this function using something like:
// findClasses("com.mypackage.mysubpackage")
// Modified from https://www.javaworld.com/article/2077477/java-tip-113--identify-subclasses-at-runtime.html
fun findClasses(pckgname: String) {
// Translate the package name into an absolute path
var name = pckgname
if (!name.startsWith("/")) {
name = "/$name"
}
name = name.replace('.', '/')
// Get a File object for the package
val url: URL = Launcher::class.java.getResource(name)
val directory = File(url.getFile())
println("Finding classes:")
if (directory.exists()) {
// Get the list of the files contained in the package
directory.walk()
.filter { f -> f.isFile() && f.name.contains('$') == false && f.name.endsWith(".class") }
.forEach {
val fullyQualifiedClassName = pckgname +
it.canonicalPath.removePrefix(directory.canonicalPath)
.dropLast(6) // remove .class
.replace('/', '.')
try {
// Try to create an instance of the object
val o = Class.forName(fullyQualifiedClassName).getDeclaredConstructor().newInstance()
if (o is MyInterfaceOrClass) {
println(fullyQualifiedClassName)
// Optionally, make a function call here: o.myFunction()
}
} catch (cnfex: ClassNotFoundException) {
System.err.println(cnfex)
} catch (iex: InstantiationException) {
// We try to instantiate an interface
// or an object that does not have a
// default constructor
} catch (iaex: IllegalAccessException) {
// The class is not public
}
}
}
}

How can I mock multiple types when the signature of a concrete method refers to another concrete type, not its interface?

I'm making use of a third party library that doesn't have any interfaces for its classes. I can use them in my structs no problem, but they have side effects that I want to avoid when unit testing.
// Somewhere there are a couple structs, with no interfaces. I don't own the code.
// Each has only one method.
type ThirdPartyEntry struct {}
func (e ThirdPartyEntry) Resolve() string {
// Do some complex stuff with side effects
return "I'm me!"
}
// This struct returns an instance of the other one.
type ThirdPartyFetcher struct {}
func (f ThirdPartyFetcher) FetchEntry() ThirdPartyEntry {
// Do some complex stuff with side effects and return an entry
return ThirdPartyEntry{}
}
// Now my code.
type AwesomeThing interface {
BeAwesome() string
}
// I have a class that makes use of the third party.
type Awesome struct {
F ThirdPartyFetcher
}
func (a Awesome) BeAwesome() string {
return strings.Repeat(a.F.FetchEntry().Resolve(), 3)
}
func NewAwesome(fetcher ThirdPartyFetcher) Awesome {
return Awesome{
F: fetcher,
}
}
func main() {
myAwesome := NewAwesome(ThirdPartyFetcher{})
log.Println(myAwesome.BeAwesome())
}
This works! But I want to write some unit tests, and so I'd like to Mock both the third party structs. To do so I believe I need interfaces for them, but since ThirdPartyFetcher returns ThirdPartyEntrys, I cannot figure out how.
I created a pair of interfaces which match up with the two third party classes. I'd like to then rewrite the Awesome struct and method to use the generic Fetcher interface. In my test, I would call NewAwesome() passing in a testFetcher, a struct which also implements the interface.
type Awesome struct {
F Fetcher
}
func NewAwesome(fetcher Fetcher) Awesome {
return Awesome{
Fetcher: fetcher,
}
}
type Entry interface {
Resolve() string
}
// Double check ThirdPartyEntry implements Entry
var _ Entry = (*ThirdPartyEntry)(nil)
type Fetcher interface {
FetchEntry() Entry
}
// Double check ThirdPartyFetcher implements Fetcher
var _ Fetcher = (*ThirdPartyFetcher)(nil)
I omit the test code because it's not relevant. This fails on the last line shown.
./main.go:49: cannot use (*ThirdPartyFetcher)(nil) (type *ThirdPartyFetcher) as type Fetcher in assignment:
*ThirdPartyFetcher does not implement Fetcher (wrong type for FetchEntry method)
have FetchEntry() ThirdPartyEntry
want FetchEntry() Entry
The signatures are different, even though I already showed that ThirdPartyEntry implements Entry. I believe this is disallowed because to would lead to something like slicing (in the polymorphic sense, not the golang sense). Is there any way for me to write a pair of interfaces? It should be the case that the Awesome class doesn't even know ThirdParty exists - it's abstracted behind the interface and injected when main calls NewAwesome.
It's not very pretty, but one way would be to:
type fetcherWrapper struct {
ThirdPartyFetcher
}
func (fw fetcherWrapper) FetchEntry() Entry {
return fw.ThirdPartyFetcher.FetchEntry()
}
I'd say mocking things that return structs vs interfaces is a relatively common problem without any great solutions apart from a lot of intermediate wrapping.

Basic API in golang antipattern?

Correct me if I'm wrong, but for my understanding of an API is that it is something that allows me to modify and request data through an interface, which is what I want to do in Go. For example I have a user interface:
interface IUser {
GetId() int
GetName() string
GetSignupDate() time
GetPermissions() []IPermission
Delete()
}
This already looks to me like active record and if I want to create a new user with a new id I would have to use new since Go doesn't support static functions as far as I know. This means I would also need a commit function in my interface, which makes it even worse for me. What am I doing wrong here?
In Go, interfaces are behavioural. That is, they describe what a thing does more than what it is. Your example looks like you're trying to write C# in Go, with your heavy use of I in front of interface classes. However, an interface that is only implemented by one type is a bit of a waste of time.
Instead, consider:
interface Deleteable { // You'd probably be tempted to call this IDeleteable
// Effective go suggests Deleter, but the grammar
// sounds weird
Delete() err
}
Now you can create a function to perform batch deletes:
func BatchDelete(victims []Deleteable) {
// Do some cool things for batching, connect to db, start a transaction
for _, victim := range(victims) {
victim.Delete() // Or arrange for this function to be called somehow.
}
}
You'd probably get started faster by creating an interface for Update, Serialize and so on, and storing your actual users/permissions/etc in concrete structs that implement those methods. (Note in Go you don't have to say that a type implements an interface, it happens "automatically"). You also don't have to have a single interface for each method (Updater, Serializable), but you can bundle them all into one interface:
type DBObject interface {
Update()
Serialize() RowType
Delete()
}
type User struct {
Id int
Name string
// ... etc
}
Remember, your model can always "Fill in" a User object to return from your API, even if the actual representation of the User object is something much more diffuse, e.g. RDF triples.
I agree with #ZanLynx comments. Go’s standard library seems to favour the interface way for APIs.
package main
import "fmt"
type S string
type I interface{ M() S }
func (s S) M() S { return s }
func API(i I) I { return i.M() }
func main() {
s := S("interface way")
fmt.Println(API(s))
}
It may be worth noting that APIs that take in a one-method interface could be re-written as taking a function type.
package main
import "fmt"
func API(f func() string) string { return f() }
func main() {
f := func() string { return "higher-order way" }
fmt.Println(API(f))
}
As an API author, one could provide both mechanisms and let the API consumer decide the style of invocation. See http://aquaraga.github.io/functional-programming/golang/2016/11/19/golang-interfaces-vs-functions.html.