Define an abstract class that inherits an infterface, but does not implement it - interface

incorporating leppies feedback it compiles - but IMO some drawbacks I want each sub class to be forced by the compiler to define their own Uri property. Code as it is now:
[<AbstractClass>]
type UriUserControl() =
inherit UserControl()
interface IUriProvider with
member this.Uri with get() = null
Interesting enough, the class I defines which inerits from above does not show a public Uri property:
type Page2() as this =
inherit UriUserControl()
let uriStr = "/FSSilverlightApp;component/Page2.xaml"
let mutable uri = new System.Uri(uriStr, System.UriKind.Relative)
do
Application.LoadComponent(this, uri)
member public this.Uri with get () = uri
I would like to define an abstract class that inherits from UserControl and my own Interface IUriProvider, but doesn't implement it. The goal is to be able to define pages (for silverlight) that implement UserControl but also provide their own Uri's (and then stick them in a list / array and deal with them as a set:
type IUriProvider =
interface
abstract member uriString: String ;
abstract member Uri : unit -> System.Uri ;
end
[<AbstractClass>]
type UriUserControl() as this =
inherit IUriProvider with
abstract member uriString: String ;
inherit UserControl()
Also the Uri in the definition - I would like to implement as a property getter - and am having issues with that as well.
this does not compile
type IUriProvider =
interface
abstract member uriString: String with get;
end

Here is a way to do it:
type IUriProvider =
abstract member UriString: string
abstract member Uri : System.Uri
[<AbstractClass>]
type UriUserControl() as this =
inherit System.Windows.Controls.UserControl()
abstract member Uri : System.Uri
abstract member UriString : string
interface IUriProvider with
member x.Uri = this.Uri
member x.UriString = this.UriString
Note that you have to provide an implementation of the interface (since all interface implementations in F# are explicit), but this can just refer back to abstract members in the class. Then you can subclass thusly:
type ConcreteUriUserControl() =
inherit UriUserControl()
override this.Uri = null
override this.UriString = "foo"

From a .NET point of view, you would need to at least provide an abstract implementation for the interface. But that again could proof problematic due to default interface accessibility, which would require some more glue again for an explicit implementation.

Related

Dart - Limit generic constrained type to sub type

i am currently working with Flutter/Dart. I want to implement a generic helper class, which puts a received input value into a generic wrapper, depending on the type.
Here the example code:
class ClassA {}
class ClassB<T> {
ClassB(this.t);
final T t;
}
class ClassC<T extends ClassA? {
ClassC(this.t);
final T t;
}
class ClassD<T> {
ClassD(this.t);
final T t;
Object getWrapper(){
final t = this.t;
return T == ClassA?
? ClassC<T>(t) //<--fails
: ClassB<T>(t);
}
}
Produces:
'T' doesn't conform to the bound 'ClassA?' of the type parameter 'T'.
ClassD is the helper which produces the wrappers. For the wrapper ClassB there is no isdue, but i could not get it to work for the wrapper ClassC. As it constrains its generic type it conflicts with the generic type of the wrapper itself, although i also included a type check there to limit the type to the constrained one.
I am wondering why this won't work and how it could be adjusted to make it work.
I tried to add a type check and adjusted it in various ways like
T == ClassA
or
T is ClassA
also including the local variable t
T == ClassA && t is ClassA

Generic Programming: How can I access a class "fromMap" factory constructor from a Generic class

How to access a class "fromMap" factory constructor from a Generic class.
For example, Here is a very simplified class and method:
abstract class DBbase<T> {
dynamic convert(dynamic input) {
T u = T.fromMap(input.toMap());
return u;
}
}
class DB<UserModel> extends DBbase {}
The **"T.fromMap" ** doesn't work a although the "UserModel" does have the method within.
If I change that line to:
UserModel u2 = UserModel.fromMap(input.toMap());
then it works, but this defeats the purpose of defining the type as a generic.

F# Interface with static member

How to define a static member in an Interface?
Why it is not possible?
I want to force a F# type (class) to have a static method to create an instance of itself from a string (JSON parsing).
I want this Interface example:
[<Interface>]
type public ILikeJson<'T> =
abstract member ToJson: unit -> string // OK
static abstract member FromJson: string -> 'T // <-- "static" is not valid here !
Alternatively a constructor from a string can do the work but a static method sounds better because it will have an appropriate name and I don't know how to define a constructor in the Interface too.
The present CLR specification states that interfaces are only implemented for object instances and do not apply for the types themselves.
C# 8 has a proposal for defining static interface members, but it is required to provide an implementation for the static methods within the interface definition itself. So you won't be able to implement a FromJson method per class.
If you try this in F#, you'll get:
FS0868: Interfaces cannot contain definitions of concrete members. You may need to define a constructor on your type to indicate that the type is a class.
One solution to this problem is to use static type constraints. They allow you to look up the existence of a method on a type.
let inline create< ^T when ^T : (static member FromJson: string -> ^T)> json =
(^T : (static member FromJson: string -> ^T) (json))
This supports any type which has a static method FromJson with the string -> T signature.
type Number(num: double) =
member _.Value = num
static member FromJson (json) = new Number(Double.Parse(json))
and to use:
create<Number> "1.5" //creates a Number(1.5)

Inheritance, Generics, and Protocols in Swift

I have a generic class of the form:
class BaseClass<T> {
var prop: T
...
}
I then have multiple subclasses of the form:
class SubClassOne: BaseClass<SomeSubClass> {
...
}
class SubClassTwo: BaseClass<SomeOtherSubClass> {
...
}
Where the type parameters SomeSubClass and SomeOtherSubClass both inherit from a common base class SomeBaseClass.
I now want to define a variable to store instances of both SubClassOne and SubClassTwo. I have tried many possibilities:
var obj: BaseClass
var obj: BaseClass<SomeBaseClass>
var obj: BaseClass<Any>
But the first attempt results in the error Reference to generic type 'BaseClass' requires arguments in <...>, and the other two result in the error Cannot assign value of type 'SubClassOne' to type ... when trying to assign a value. I even tried to trick the Swift compiler into inferring the type for me by initializing an array:
var testArray = [SubClassOne(), SubClassTwo()]
But even this failed, resulting in the error Heterogeneous collection literal could only be inferred to [Any]; add explicit type annotation if this is intentional. Indeed, the only type annotation that successfully allows storage of both SubClasses is Any or AnyObject. Is it possible to store these instances with a more specific type? If not, why?
The reason it's important to do so is that I ultimately want to get the property prop from the stored variable obj. I am unable to do so if obj is stored as Any. I am also unable to simply cast it to SubClassOne or SubClassTwo because the method itself where I am trying to access the properties is a generic method, and which of SubClassOne or SubClassTwo to cast to depends on the generic type parameter of the method:
func castObj<T>(asType: T.Type) {
(self.obj as? T).prop
}
Which would be called as: castObj(asType: SubClassOne.self) or castObj(asType: SubClassTwo.self). However, we run into the same problem: the only generic type parameter constraint I can define that accepts both SubClassOne and SubClassTwo is Any, and then the Swift compiler complains: Value of type 'T' has no member 'prop'.
As a workaround I tried to define a protocol that encapsulates the desired property:
protocol HasProp {
var prop: SomeBaseClass { get }
}
Then I added this to the declaration of SubClassOne and SubClassTwo. However this resulted in still another error: Type 'SubClassOne' does not conform to protocol 'HasProp'. This confuses me as well, since SubClassOne and SubClassTwo both inherit prop from BaseClass<SomeSubClass> and so actually do conform to the protocol.
In summary:
Is it possible to store instances of SubClassOne and SubClassTwo with a more specific type that gives access to properties of BaseClass? If not, why?
Why do the SubClasses not conform to the protocol as expected?
How can I change the design to attain my desired behavior?
The problem is that at the moment the function castObj has no type constraints for its generic parameter, T. By giving a type constraint of BaseClass you should be fine, since BaseClass has both properties.
func castObj<T: BaseClass>(asType: T.Type) {
(self.obj as? T).propOne
(self.obj as? T).propTwo
}
In your example, the type of propTwo was common to both subclasses and the type of propOne was specialized. Make your design reflect that.
[was]
class BaseClass<T,U> {
var propOne: T
var propTwo: U
...
}
class SubClassOne: BaseClass<SomeSubClass, SomeClass> {}
class SubClassTwo: BaseClass<SomeOtherSubClass, SomeClass> {}
[could be]
class BaseClass<U> {
var propTwo: U
...
}
class SubClassOne<T>: BaseClass<SomeClass> {
var propOne: T
...
}
class SubClassTwo<T>: BaseClass<SomeClass> {
var propOne: T
...
}
The point is to keep common things in the base class and compose your specializations.
There's a fundamental misconception that SubclassOne and SubclassTwo are in the same inheritance hierarchy. Because of the generic type, they inherit from different base classes. You cannot mix and match them.
Think about it. With inheritance you should be able to use any subclass anywhere where you have the base class, so in your test example:
var testArray = [SubClassOne(), SubClassTwo()]
What type would the right hand side of the following expressions have to be?
testArray[0].prop = something
And this one
testArray[1].prop = something;
In SubClassOne, the type of prop is SomeSubClass and in SubClassTwo the type of prop must be SomeOtherSubClass.
The only way for you to get this to work is for prop to be declared as SomeBaseClass and that removes the necessity for BaseClass to be generic.
Edit
Why doesn't the protocol work?
The problem with the protocol is that you define the property as having the type of the base class but it is read/write. A property in an implementation of the protocol cannot fulfill the contract with a property that is specialised to one of the subclasses because other bits of code need to be able to assign any instance of the base class to the property.
protocol MyProtocol
{
var prop: BaseClass
}
struct MyImplementation: MyProtocol
{
var prop: SubClass
}
class BaseClass {}
class SubClass: BaseClass {}
class DifferentSubClass: BaseClass {}
var instance: MyProtocol = MyImplementation()
instance.prop = DifferentSubClass()
// Should be legal because the protocol says so but the type of prop in instance is SubClass.

Haxe java.lang.Object Equivalent

Haxe allows class inheritance hierarchies
class Honda extends Car {
...
}
is there a common inheritance hierarchy root for all objects? I have a generic container class that could contain any object and I want to be able to declare
var _contents:Object; //Any class instance in _contents
How can I do this?
You can also use {} as a type, which will accept class instances as well as anonymous objects :
var _contents:{};
We also have Dynamic, which basically means "anything" (not only objects, but also primitives like Bool, Int, etc).
If your class is a generic container, you may want to type its content, though, using type parameters:
class Container<T> {
var _contents:T;
public function new(contents:T):Void {
_contents = contents;
}
}
And then:
var arrayContainer = new Container([]);
var stuffContainer = new Container({foo:"bar"});
var classContainer = new Container( new Stuff() );
The inheritance root for classes is Class<T> so the following should work:
var _contents:Class<T>;
However, to store an Enum, you would have to use Enum<T> instead.
From the manual:
There is a special type in Haxe which is compatible with all classes:
Define: Class<T>
This type is compatible with all class types which means that all classes (not their instances) can be assigned to it. At compile-time, Class<T> is the common base type of all class types. However, this relation is not reflected in generated code.
This type is useful when an API requires a value to be a class, but not a specific one. This applies to several methods of the Haxe reflection API.