Check if property or method exists at runtime? Check if Trait exists at runtime? - methods

Looking for the proper way to do
if(self.MyProperty) { /* ... */ }
error: attempted access of field MyProperty on type MyType, but no field with that name was found
or
if(self.MyMethod){ /* ... */ }
error: attempted to take value of method MyMethod on type MyType
As a last resort, at least how does one check if a Trait is Implemented?

This concept doesn't exist in Rust. While there is some limited downcast capability through Any, this should be used as a last resort. What you should do is create a new trait that exposes all of these decisions for you.
Reusing your example of a my_method method:
trait YourTrait {
fn try_my_method(&self, arg: SomeArg) -> Option<MyMethodResult> {
None
}
}
impl YourTrait for SomeType {
fn try_my_method(&self, arg: SomeArg) -> Option<MyMethodResult> {
Some(self.my_method(arg))
}
}
In your code you can then call
if let Some(result) = self.try_my_method() {
/* ... */
}

Related

Refactoring method to be part of an interface

I am an ex python dev sometimes struggling with the explicit nature of Go.
I am trying here to refactor some code in order to be able move a method from one structure to be part of an interface.
But the process seems weird to me, I wish to confirm I am not doing something incorrectly.
I have the following interfaces, structure and methods:
type Executing interface {
Execute()
}
type MyExecuter struct {
attribut1 string
}
//The function I wish to move
func (exe1 *MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 *MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
func GetExecuter () Executer{
return MyExecuter{attribut1: "test"}
}
So here I have a generic interface Execute, this interface will be accessed by the object returned by the GetExecuter method.
Now, as part of the implementation of one of my Executer, I want to move the Format method as part of an interface.
So I am doing the following:
type Formatting interface {
format() string
}
type Formatter struct {}
func (formatter *Formatter) format(exe1 *MyExecuter) (string) {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
So I create a new interface, a new empty structure, and update my function to take as attribute my previous structure.
While this seems to work, it seems to me this is a bit convoluted. Specially the part where I need to add a reference to my initial object as attribute of the method. Am I doing something wrong here, or this is the right way?
Your Executer implementation already implements the Formatting interface:
type Executing interface {
Execute()
}
type Formatting interface {
format() string
}
func (exe1 MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
v:=MyExecuter{}
// Here, v implements Executing and Formatting interfaces
One thing to note here: Your code shows pointer receivers. That means the methods are defined for *MyExecuter, but not for MyExecuter. So you have to pass pointers to the struct instance for this to work. Or, as I did above, use the value receivers so the methods are defined for both MyExecuter and *MyExecuter.

Kotlin: Specify input-constraints in interface

Lets say I have the following interface:
interface MathThing {
fun mathFunction(x : Int)
}
Let's say the constraint I want to put onto this function is that x cannot be negative.
How can I make sure that every time this (or any other arbitrary) condition isn't met on a object of type MathThing, a (custom) exception is thrown?
One way is to use a wrapper class for your function parameters. You can make an extension function so it's a little easier to pass values to the function.
data class NonNegative(val value: Int) {
init{ if (value < 0) throw IllegalArgumentException("Input must not be negative.") }
}
fun Int.nonNegative() = NonNegative(this)
interface MathThing {
fun mathFunction(x : NonNegative)
}

How to trigger visitInputObject method on custom directive?

I'm building a custom directive in which I'm hoping to validate entire input objects. I'm using the INPUT_OBJECT type with the visitInputObject method on SchemaDirectiveVisitor extended class.
Every time I run a mutation using the input type then visitInputObject does not run.
I've used the other types/methods like visitObject and visitFieldDefinition and they work perfectly. But when trying to use input types and methods they will not trigger.
I've read all the available documentation I can find. Is this just not supported yet?
Some context code(Not actual):
directive #validateThis on INPUT_OBJECT
input MyInputType #validateThis {
id: ID
someField: String
}
type Mutation {
someMutation(myInput: MyInputType!): SomeType
}
class ValidateThisDirective extends SchemaDirectiveVisitor {
visitInputObject(type) {
console.log('Not triggering');
}
}
All the visit methods of a SchemaDirectiveVisitor are ran at the same time -- when the schema is built. That includes visitFieldDefinition and visitFieldDefinition. The difference is that when we use visitFieldDefinition, we often do it to modify the resolve function for the visited field. It's this function that's called during execution.
You use each visit methods to modify the respective schema element. You can use visitInputObject to modify an input object, for example to add or remove fields from it. You cannot use it to modify the resolution logic of an output object's field. You should use visitFieldDefinition for that.
visitFieldDefinition(field, details) {
const { resolve = defaultFieldResolver } = field
field.resolve = async function (parent, args, context, info) {
Object.keys(args).forEach(argName => {
const argDefinition = field.args.find(a => a.name === argName)
// Note: you may have to "unwrap" the type if it's a list or non-null
const argType = argDefinition.type
if (argType.name === 'InputTypeToValidate') {
const argValue = args[argName]
// validate here
}
})
return resolve.apply(this, [parent, args, context, info]);
}
}

Interface and Implementation

In following code snippet -
type Input interface {
Name() string
}
type Abc interface {
Do(Input)
}
type InputImpl struct {
}
func (InputImpl) Name() string {
return "sample-impl"
}
type AbcImpl struct {
}
func (abcImpl *AbcImpl) Do(input Input){
// do something
}
AbcImpl struct is an implementation of Abc interface, but changing last function like this -
func (abcImpl *AbcImpl) Do(input InputImpl){
// do something
}
Now the AbcImpl is not implementing Abc anymore, though InputImpl is implementing Input interface !
Am I missing something or it's compulsory to have exact same signature (not event Impls) as the interface to be a legitimate implementation?
Yes, you do have to follow the method signature you specified.
If you don't follow the signature, it will not be called "implementing".
an example: interface example
from tour of Go: There is no explicit declaration of intent, no "implements" keyword.
It is compulsory to use the very exact same signature when implementing an interface in Go. You can't implement it otherwise.

Can't access method from another package by var.MethodName()

I have a package containing some structure and functions associated with it:
package samplepkg
type SampleStruct struct {
FirstString string
SecondString string
}
func init() {
// some operations
}
func CheckSomething(s *SampleStruct) bool {
// check something
}
Now I'm trying to run this function in another package:
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = samplepkg.SampleStruct{"a", "b"}
if s.CheckSomething() {
// do some operations
}
}
But I get an error that s.CheckSomething is undefined. (&s).CheckSomething gives the same result. I can access s.FirstString and s.SecondString as well as use this method by calling
if samplepkg.CheckSomething(&s) {
// do some operations
}
But I feel it could be written in a better way. I'm aware that Go is not object-oriented language but is method invocation like this possible?
In Golang a Method set is defined as:
A type may have a method set associated with it. The method set of an
interface type is its interface. The method set of any other type T
consists of all methods declared with receiver type T. The method set
of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T). Further rules apply to structs containing embedded fields,
as described in the section on struct types. Any other type has an
empty method set. In a method set, each method must have a unique
non-blank method name.
There is a mistake because you are using the pointer receiver with method when calling the function. So change the function when defining to method as:
func init() {
// some operations
}
func(s *SampleStruct) CheckSomething() bool {
// check something
}
Or when calling the method it should be function with argument SampleStruct which will be like
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = &samplepkg.SampleStruct{"a", "b"}
if CheckSomething(s) {
// do some operations
}
}

Resources