How to pass a class type as a function parameter
You are approaching it in the wrong way: in Swift, unlike Objective-C, classes have specific types and even have an inheritance hierarchy (that is, if class B
inherits from A
, then B.Type
also inherits from A.Type
):
class A {}
class B: A {}
class C {}
// B inherits from A
let object: A = B()
// B.Type also inherits from A.Type
let type: A.Type = B.self
// Error: 'C' is not a subtype of 'A'
let type2: A.Type = C.self
That's why you shouldn't use AnyClass
, unless you really want to allow any class. In this case the right type would be T.Type
, because it expresses the link between the returningClass
parameter and the parameter of the closure.
In fact, using it instead of AnyClass
allows the compiler to correctly infer the types in the method call:
class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: T.Type, completionHandler handler: ((T) -> ())) {
// The compiler correctly infers that T is the class of the instances of returningClass
handler(returningClass())
}
Now there's the problem of constructing an instance of T
to pass to handler
: if you try and run the code right now the compiler will complain that T
is not constructible with ()
. And rightfully so: T
has to be explicitly constrained to require that it implements a specific initializer.
This can be done with a protocol like the following one:
protocol Initable {
init()
}
class CityInfo : NSObject, Initable {
var cityName: String?
var regionCode: String?
var regionName: String?
// Nothing to change here, CityInfo already implements init()
}
Then you only have to change the generic constraints of invokeService
from <T>
to <T: Initable>
.
Tip
If you get strange errors like "Cannot convert the expression's type '()' to type 'String'", it is often useful to move every argument of the method call to its own variable. It helps narrowing down the code that is causing the error and uncovering type inference issues:
let service = "test"
let params = ["test" : "test"]
let returningClass = CityInfo.self
CastDAO.invokeService(service, withParams: params, returningClass: returningClass) { cityInfo in /*...*/
}
Now there are two possibilities: the error moves to one of the variables (which means that the wrong part is there) or you get a cryptic message like "Cannot convert the expression's type ()
to type ($T6) -> ($T6) -> $T5
".
The cause of the latter error is that the compiler is not able to infer the types of what you wrote. In this case the problem is that T
is only used in the parameter of the closure and the closure you passed doesn't indicate any particular type so the compiler doesn't know what type to infer. By changing the type of returningClass
to include T
you give the compiler a way to determine the generic parameter.
How to pass a class type as parameter?
In TypeScript, you can construct a new type, something like:
type Class<T> = new (...args: any[]) => T
Which you can then use this way:
function register(command: Class<Command>) {
new command()
}
This should constrain TypeScript to ONLY accept classes which construct or extend the Command type.
EDIT:
Sorry, missed something when I evaluated your example. Your class Command
is generic enough that almost any constructable object will overlap. What it's missing is constraints.
- The constructor will take
any
first argument, undefined or not, so any class which has a constructor accepting zero or one arguments will match - The signature of the object that will be returned is empty, no methods or properties exist to identify it and so any methods/props will "fall-through" and be allowed as an "extension" of your class
We can over come either of these by modifying either properties or methods required for the Command
class, thus constraining derived types to that explicit signature
If we want to narrow the possible matches by adding a method or property specific to Command
, then we get the desired behavior you've outlined.
export namespace customCommand {
export type Class<T> = new (...args: any[]) => T
export class Command {
public constructor(parameter?: any) {
}
picard (): string {
return 'Make it so.'
}
}
export function register(command: Class<Command>) {
new command()
}
}
/*
Argument of type 'MapConstructor' is not assignable to
parameter of type 'Class<Command>'. Property 'picard'
is missing in type 'Map<any, any>' but required in
type 'Command'. ts(2345)
*/
customCommand.register(Map)
/*
Argument of type 'ObjectConstructor' is not assignable to
parameter of type 'Class<Command>'. The 'Object' type is
assignable to very few other types. Did you mean to use
the 'any' type instead? Property 'picard' is missing in
type 'Object' but required in type 'Command'. ts(2345)
*/
customCommand.register(Object)
/* No error */
customCommand.register(customCommand.Command)
How to pass class type as an parameter to function?
You could do something like this:
List<A> list = (...);
public static void print(Class klass) {
for(A a : list) {
if(klass.isInstance(a)) {
System.out.println(a);
}
}
}
To use it:
print(C.class);
Or
C c = new C();
print(c.getClass());
Pass class type as a function parameter and use as? to cast the class
Swift 4.2
You can use a generic function and restrict the type parameter to be a Section.
import Foundation
class Section {}
class TimeSection: Section {}
class TaskSection: Section {}
class NoSection {}
let timeSection = TimeSection()
let taskSection = TaskSection()
let sections = [timeSection, taskSection]
func findSection<T: Section>(from classType: T.Type) {
for section in sections {
guard let section = section as? T else { continue }
print("Found section: \(section)")
}
}
findSection(from: TimeSection.self) // Found section: __lldb_expr_9.TimeSection
findSection(from: TaskSection.self) // Found section: __lldb_expr_9.TaskSection
findSection(from: NoSection.self) // won't compile
Python - how to pass to a function argument type of a class object (typing)
Depending on whether you meant to pass a class (type) or an instance of a class, you’re looking for either typing.Type
or simply the class.
Here’s a simple example to explain both situations:
from typing import Type, TypeVar
class Vehicle:
def __init__(self):
print("Creating a %s" % self.__class__.__name__)
def move(self):
print("This %s is moving…" % self.__class__.__name__)
TVehicle = TypeVar("TVehicle", bound=Vehicle)
class Car(Vehicle):
def honk(self) -> None:
print("tuuuuut")
class Bike(Vehicle):
def ring(self) -> None:
print("ring")
class Dog:
def bark(self) -> None:
print("woof!")
def move(v: Vehicle) -> None:
v.move()
def instantiate(class_to_instantiate: Type[TVehicle]) -> TVehicle:
return class_to_instantiate() # create an instance
move(Bike())
move(Car())
instantiate(Bike).ring()
instantiate(Car).honk()
#instantiate(Dog)
Car
and Bike
inherit from Vehicle
, so they both get at least the move
method and the custom __init__
, which reveals the name of the class that invoked it.
Now, in the first function, move
, one simply wants to specify that the argument v
should be an instance of a Vehicle
. The function calls Vehicle
’s move
method, which will reveal the name of the instance’s class from which the call originated.
In the second function, instantiate
, the goal is to create an instance of a class. This works through type variables, which allow you in this example to specify that there’s a relation between the function’s input argument and output argument: if I were to call instantiate(Bike)
, I want the return type to be an instance of the Bike
class, so that I may legally call its ring
method. If you were to replace the TVehicle
in this function definition simply by Vehicle
, your type checking program would complain, because the return type would then be an instance of the Vehicle
class, for which you do not have a guarantee that the ring
method exists.
Finally, the Type
part that you see in the argument of instantiate
simply allows you to call the function with a class, so not with an instance of that class. This is useful e.g. in cases where you want to delay instantiation of a class.
Note that this is an example to explain how to do it. In a more professional setting, Vehicle
would likely be an abstract base class and some methods here could be given as class methods.
Side notes on your code example:
- Note that if you don’t intend to write code that also works in Python2, you shouldn’t inherit from
object
(ref). - Classes are typically written with
CapWord
names, as specified in PEP8, the Python style guide. Following this style makes your code more easily understandable by other developers.
How can I pass a class method as a parameter to another function and later call it, preferably making the variable class method signature explicit?
How would I need to change the above code to implement the same thing
using templates instead ofstd::function
+std::bind
?And how about lambdas instead of
std::function
+std::bind
? I
still want to callB:myWay()
andB::otherWay()
but using lambdas.
I don't want to substituteB:myWay()
andB::otherWay()
with
lambdas.
You can use a lambda, yes.
Something like [this]() { return myWay(); }
that:
- captures
this
, and - calls a method of the current object.
[Demo]
#include <iostream> // cout
class A {
protected:
template <typename F>
void complexMethod(F&& f) { f(); }
};
class B : public A {
void myWay() { std::cout << "myWay\n"; }
void otherWay() { std::cout << "otherWay\n"; }
public:
void doingSomething() {
complexMethod([this]() { return myWay(); });
}
void doingAnotherThing() {
complexMethod([this]() { return otherWay(); });
}
};
int main() {
B b{};
b.doingSomething();
b.doingAnotherThing();
}
// Outputs:
//
// myWay
// otherWay
Is there any implementation technique (one of the above or some other)
were I would be able to makevariableMethod
return type and
parameters explicit? How would I do it?
You could use const std::function<bool(int,double)>& f
as the parameter receiving a function for complexMethod
. And still pass a lambda. Notice though lambdas are now receiving (int i, double d)
(it could be (auto i, auto d)
as well).
[Demo]
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
bool complexMethod(const std::function<bool(int,double)>& f, int i, double d)
{ return f(i, d); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](int i, double d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Notice also the same could be accomplished with templates, although you wouldn't be making the signature explicit.
[Demo]
#include <functional> // function
#include <ios> // boolalpha
#include <iostream> // cout
class A {
protected:
template <typename F, typename... Args>
auto complexMethod(F&& f, Args&&... args) -> decltype(f(args...))
{ return f(args...); }
};
class B : public A {
bool myWay(int a, double b) { return a < static_cast<int>(b); }
bool otherWay(int a, double b) { return a*a < static_cast<int>(b); }
public:
bool doingSomething(int a, double b) {
return complexMethod([this](auto i, auto d) {
return myWay(i, d); }, a, b);
}
bool doingAnotherThing(int a, double b) {
return complexMethod([this](auto i, auto d) {
return otherWay(i, d); }, a, b);
}
};
int main() {
B b{};
std::cout << std::boolalpha << b.doingSomething(3, 5.5) << "\n";
std::cout << std::boolalpha << b.doingAnotherThing(3, 5.5) << "\n";
}
// Outputs:
//
// true
// false
Which technique is recommended? Why (speed, flexibility,
readility...)?
Item 34 of Scott Meyer's Effective Modern C++ book is titled Prefer lambdas to std::bind
. It ends with a summary saying: Lambdas are more readable, more expressive, and may be more efficient than using std::bind
. However, it also mentions a case when std::bind
may be useful over lambdas.
Swift - How to use a class type as a parameter / variable
First read Metatype Type in the The Swift Programming Language. Once read continue with the answer.
From that you have learnt that you can declare a function parameter's type to be the type of types (you are allowed to go crosseyed), AKA metatype, and can therefore pass a type to a function. Combine that with generics and Swift's type inference and you could declare your function as:
func sortFileArrayByType<T>(fileAttributeKeyString : String,
attributeType : T.Type,
fileURLArray : [URL]
) -> [(url: URL, attribute: T)]
where T : Comparable
This adds the parameter attributeType
whose type is the metatype of T
where T
will be inferred. For example the metatype String.self
could be passed and T
will be inferred to be String
.
The where
clause constrains T
so that only types which are Comparable
are allowed, this is required to enable the function to do sorting. File attributes can be Date
, String
and NSNumber
valued; unfortunately the latter does not conform to Comparable
so you need to add an extension to make it, the following will suffice:
extension NSNumber : Comparable
{
public static func <(a : NSNumber, b : NSNumber) -> Bool { return a.compare(b) == .orderedAscending }
public static func ==(a : NSNumber, b : NSNumber) -> Bool { return a.compare(b) == .orderedSame }
}
Within the body of the function you need to declare your array of tuples to have attributes of type T
:
var tupleArrayWithURLandAttribute : [(url: URL, attribute: T)] = []
and when you add entries you need to cast the value returned by attributesOfItem
to be T
:
tupleArrayWithURLandAttribute.append((url: url, attribute: value as! T))
Note the use of as!
here, you must match the attribute name and the type of its value correctly in the function call or you will get a runtime abort. Handling this as a soft error, if needed, is left as an exercise.
There are a number of typos etc. in the code you posted, they are left for you to fix, having done that your function should work. A call might look like:
let ans = sortFileArrayByType2(fileAttributeKeyString: "NSFileCreationDate",
attributeType: Date.self,
fileURLArray: urlArray)
and the type of ans
in this case will be [(url: URL, attribute: Date)]
HTH
How to pass a Swift type as a method argument?
You have to use a generic function where the parameter is only used for type information so you cast it to T
:
func doSomething<T>(_ a: Any, myType: T.Type) {
if let a = a as? T {
//…
}
}
// usage
doSomething("Hello World", myType: String.self)
Using an initializer of the type T
You don’t know the signature of T
in general because T
can be any type. So you have to specify the signature in a protocol.
For example:
protocol IntInitializable {
init(value: Int)
}
With this protocol you could then write
func numberFactory<T: IntInitializable>(value: Int, numberType: T.Type) -> T {
return T.init(value: value)
}
// usage
numberFactory(value: 4, numberType: MyNumber.self)
Related Topics
What Is the Reduce() Function Doing, in Swift
Should Conditional Compilation Be Used to Cope With Difference in Cgfloat on Different Architectures
Alamofire Asynchronous Completionhandler For Json Request
Include Swiftui Views in Existing Uikit Application
How to Access Nswindow from @Main App Using Only Swiftui
Remove Element from Collection During Iteration with Foreach
Swift - Custom Setter on Property
Generic Swift 4 Enum With Void Associated Type
Ios13 Navigation Bar Large Titles Not Covering Status Bar
How to Configure Contextmenu Buttons For Delete and Disabled in Swiftui
Break a Number Up to an Array of Individual Digits
Unowned Vs. Weak. Why We Should Prefer Unowned
Can You Override Between Extensions in Swift or Not? (Compiler Seems Confused!)
Swift Spritekit Adding Button Programmatically
Swift 3: Set Finder Label Color