Can I tell the interface to default the properties I don't supply to null? What would let me do this
No. You cannot provide default values for interfaces or type aliases as they are compile time only and default values need runtime support
Alternative
But values that are not specified default to undefined in JavaScript runtimes. So you can mark them as optional:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
And now when you create it you only need to provide a:
let x: IX = {
a: 'abc'
};
You can provide the values as needed:
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
Answer from basarat on Stack OverflowCan I tell the interface to default the properties I don't supply to null? What would let me do this
No. You cannot provide default values for interfaces or type aliases as they are compile time only and default values need runtime support
Alternative
But values that are not specified default to undefined in JavaScript runtimes. So you can mark them as optional:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
And now when you create it you only need to provide a:
let x: IX = {
a: 'abc'
};
You can provide the values as needed:
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
You can't set default values in an interface, but you can accomplish what you want to do by using optional properties:
Simply change the interface to:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
You can then do:
let x: IX = {
a: 'abc'
}
And use your init function to assign default values to x.b and x.c if those properies are not set.
I am using SWIG to generate csharp bindings for some C++ code. I was hoping to write an Interface that wraps the bindings, for convenience. My interface currently looks similar to this:
namespace GameName
{
public interface PlayerInterface
{
public byte Id
{
get
{
return Game.Players[this].id;
}
set
{
Game.Players[this].id = value;
}
}
public byte Score
{
get
{
return Game.Players[this].score;
}
set
{
Game.Players[this].score= value;
}
}
}
}Game.Players is map from csharp objects to objects generated by SWIG.
When compiling, my class that implements the interface yields `The name 'Id' does not exist in the current context` (Same for Score)
These docs seem to indicate that providing explicit default properties is possible: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/interface-properties
The example in the docs seems incomplete. Is it possible to do what I'm asking?
You can't set a default value to a property of an interface.
Use abstract class in addition to the interface (which only sets the default value and doesn't implement anything else):
public interface IA {
int Prop { get; }
void F();
}
public abstract class ABase : IA {
public virtual int Prop
{
get { return 0; }
}
public abstract void F();
}
public class A : ABase
{
public override void F() { }
}
With C#8, interfaces can have a default implementation. https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/
In the following two interfaces:
public interface Defaultable
{
public static object Default { get; } = new object();
}
public interface Defaultable<T> : Defaultable
{
public static T Default { get; } = new T();
}The top one works fine, but the bottom one throws an error:
Cannot create an instance of the variable type 'T' because it does not have the new() constraint
Why can I have a default value in non-generic interfaces, but not generic ones?
Edit: I should specify that I have nullable enabled, and I do not want the properties to be able to return null (default being a Null Object Pattern of sorts).
Virtuals may have defaults. The defaults in the base class are not inherited by derived classes.
Which default is used -- ie, the base class' or a derived class' -- is determined by the static type used to make the call to the function. If you call through a base class object, pointer or reference, the default denoted in the base class is used. Conversely, if you call through a derived class object, pointer or reference the defaults denoted in the derived class are used. There is an example below the Standard quotation that demonstrates this.
Some compilers may do something different, but this is what the C++03 and C++11 Standards say:
8.3.6.10:
A virtual function call (10.3) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object. An overriding function in a derived class does not acquire default arguments from the function it overrides. Example:
struct A { virtual void f(int a = 7); }; struct B : public A { void f(int a); }; void m() { B* pb = new B; A* pa = pb; pa->f(); //OK, calls pa->B::f(7) pb->f(); //error: wrong number of arguments for B::f() }
Here is a sample program to demonstrate what defaults are picked up. I'm using structs here rather than classes simply for brevity -- class and struct are exactly the same in almost every way except default visibility.
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using std::stringstream;
using std::string;
using std::cout;
using std::endl;
struct Base { virtual string Speak(int n = 42); };
struct Der : public Base { string Speak(int n = 84); };
string Base::Speak(int n)
{
stringstream ss;
ss << "Base " << n;
return ss.str();
}
string Der::Speak(int n)
{
stringstream ss;
ss << "Der " << n;
return ss.str();
}
int main()
{
Base b1;
Der d1;
Base *pb1 = &b1, *pb2 = &d1;
Der *pd1 = &d1;
cout << pb1->Speak() << "\n" // Base 42
<< pb2->Speak() << "\n" // Der 42
<< pd1->Speak() << "\n" // Der 84
<< endl;
}
The output of this program (on MSVC10 and GCC 4.4) is:
Base 42
Der 42
Der 84
This was the topic of one of Herb Sutter's early Guru of the Week posts.
The first thing he says on the subject is DON'T DO THAT.
In more detail, yes, you can specify different default parameters. They won't work the same way as the virtual functions. A virtual function is called on the dynamic type of the object, while the default parameter values are based on the static type.
Given
class A {
virtual void foo(int i = 1) { cout << "A::foo" << i << endl; }
};
class B: public A {
virtual void foo(int i = 2) { cout << "B::foo" << i << endl; }
};
void test() {
A a;
B b;
A* ap = &b;
a.foo();
b.foo();
ap->foo();
}
you should get A::foo1 B::foo2 B::foo1
Interfaces are reference types.
A field of an interface type will always be one pointer wide, and will default to null.
If you assign a struct that implements the interface, the struct will be boxed, and the field will contain a reference to the boxing object.
As SLaks noted, a variable which is of an interface type will behave as a reference holder which is will be known known never to contain anything other than either null or a reference to object which implements the interface. As with all reference holders, the default value will be null.
A variable which is of a generic type which is constrained to an interface type (e.g. in class
Thing<T> where T:IComparable<T>
{T foo;
...}
field Foo will have the same default value as whatever the actual type substituted for T. For example, given
struct SimplePoint : IComparable<SimplePoint>
{public int x,y;
public int CompareTo(SimplePoint other)
{...}
...}
then within Thing<SimplePoint>, the field Foo would have the default value (0,0).
Incidentally, it's worthwhile to note that while a conversion from a structure type to any reference type, including an interface it implements, will yield a reference to a new heap object containing a snapshot of the structure's fields, conversion of that reference to other reference types will yield a reference to the same heap instance.
I have an interface with two functions to enable and disable an outline on an actor. Because the functionality will remain the same across all actors who inherit the interface, is it possible to set up a default implementation so I don't have to re-set up the nodes in every actor?
Wow, everybody is such a pessimist around here. The answer is yes.
It ain't trivial: by the end, we'll have the core function, a supporting struct, a wrapper function, and a macro around the wrapper function. In my work I have a set of macros to automate all this; once you understand the flow it'll be easy for you to do the same.
I've written this up elsewhere, so here's a detailed external link to supplement the summary here: http://modelingwithdata.org/arch/00000022.htm
We'd like to turn
double f(int i, double x)
into a function that takes defaults (i=8, x=3.14). Define a companion struct:
typedef struct {
int i;
double x;
} f_args;
Rename your function f_base, and define a wrapper function that sets defaults and calls
the base:
double var_f(f_args in){
int i_out = in.i ? in.i : 8;
double x_out = in.x ? in.x : 3.14;
return f_base(i_out, x_out);
}
Now add a macro, using C's variadic macros. This way users don't have to know they're
actually populating a f_args struct and think they're doing the usual:
#define f(...) var_f((f_args){__VA_ARGS__});
OK, now all of the following would work:
f(3, 8); //i=3, x=8
f(.i=1, 2.3); //i=1, x=2.3
f(2); //i=2, x=3.14
f(.x=9.2); //i=8, x=9.2
Check the rules on how compound initializers set defaults for the exact rules.
One thing that won't work: f(0), because we can't distinguish between a missing value and
zero. In my experience, this is something to watch out for, but can be taken care of as
the need arises---half the time your default really is zero.
I went through the trouble of writing this up because I think named arguments and defaults really do make coding in C easier and even more fun. And C is awesome for being so simple and still having enough there to make all this possible.
Yes. :-) But not in a way you would expect.
int f1(int arg1, double arg2, char* name, char *opt);
int f2(int arg1, double arg2, char* name)
{
return f1(arg1, arg2, name, "Some option");
}
Unfortunately, C doesn't allow you to overload methods so you'd end up with two different functions. Still, by calling f2, you'd actually be calling f1 with a default value. This is a "Don't Repeat Yourself" solution, which helps you to avoid copying/pasting existing code.