I still don't understand the usage of override in solidity.
I know the how to write code of override, but I have no idea when I should use them.
Question 1: Is it just for write less code in inherited contract?
Question 2: If I override the function in son-contract, would it affect the function of father-contract?
Is it just for write less code in inherited contract?
Generally, you can use overriding if you want to change a default behavior. Here goes a silly example that assumes most vehicles have a steering wheel, so that's the default option - but it's overridden for motorbikes.
pragma solidity ^0.8;
contract Vehicle {
function turnRight() virtual external {
turnSteeringWheel();
}
}
contract Car is Vehicle {
// no need to override turning, car has a steering wheel
}
contract Motorbike is Vehicle {
// motorbike has a handlebar - not a steering wheel
// so turning a steering wheel would not work
function turnRight() override external {
turnHandlebar();
}
}
Overriding is also useful when you let someone else expand on your code. For example the OpenZeppelin ERC20 implementation allows you to override their default number of decimals.
pragma solidity ^0.8;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyContract is ERC20 {
constructor() ERC20("MyToken", "MyT") {}
function decimals() override public pure returns (uint8) {
return 2;
}
}
If I override the function in son-contract, would it affect the function of father-contract?
The function in the parent contract is not executed, unless the parent function is explicitly called with the super keyword.
pragma solidity ^0.8;
contract Parent {
function foo() virtual public pure returns (uint) {
return 1;
}
}
contract Child is Parent {
// not calling the Parent function, returning 2
function foo() override public pure returns (uint) {
return 2;
}
}
contract Child2 is Parent {
// calling the Parent function from within the Child function
function foo() override public pure returns (uint) {
uint returnedFromParent = super.foo();
// 1 plus 1, returns 2
return returnedFromParent + 1;
}
}
Related
There are 2 classes inherited from parent:
abstract class Parent{
abstract fun prepare()
abstract fun act()
}
class Child1:Parent(){
fun prepare()
fun act()
}
class Child2:Parent(){
fun prepare()
fun act()
}
I need to modify only method act() just to perform some action before it and run it after:
class Modify (parent:Parent):parent{
override fun act(){
...//modification
parent.act() //from Child1 or Child2 depends
}
}
class Modify1 (parent:Parent):parent{}
class Modify2 (parent:Parent):parent{}
The idea is to have several modificators and use them arbitrarily both for modified and not modified instances along with using several serial modificators:
val modifiedChild1:Parent = Modify1 ( Modify3( Child1() ) )
val modifiedChild2:Parent = Modify1 ( Child2() )
val notModified1:Parent = Child1 ()
Please advise if this concept is correct and how to implement it. Thanks.
the only way I found: is to add an interface as listener.
But in that case, it is not possible to use Modify() as a function and possibility perform several modifications.
If you're interested in modifying the public functions of Parent, you can use the Decorator pattern to create a wrapper class and override the functions. For example:
// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0
abstract class Parent {
abstract fun prepare()
abstract fun act()
}
class ParentDecorator(val parent: Parent): Parent() {
override fun prepare() {
// modification
parent.prepare()
// modification
}
override fun act() {
// modification
parent.act()
// modification
}
}
class Child: Parent() { ... }
val child = Child()
val decoratedChild = ParentDecorator(child)
decoratedChild.prepare()
// will call the modifications around the call to the
// nested child instance
This only works if the parent is abstract, open, or is an interface, and only affects the public functions that you override in the Decorator.
Note - this example is a tad awkward - we're creating an instance of Parent to override all of its functions and wrap another instance of Parent, delegating the real function to that wrapped instance. It would be much better to make Parent an interface if you want to create a Decorator. For example:
// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0
interface Stuff {
fun prepare()
fun act()
}
class StuffDecorator(val realStuff: Stuff): Stuff {
override fun prepare() {
// modification
realStuff.prepare()
// modification
}
override fun act() {
// modification
realStuff.act()
// modification
}
}
class Child: Stuff { ... }
// could extend another class that implements Stuff
val child = Child()
val decoratedChild = StuffDecorator(child)
decoratedChild.prepare()
// will call the modifications around the call to the
// nested child instance
However, if you're stuck with an existing open/abstract Parent class, this is the best you can do)
If you want to do this is non-public functions, #cyberbrain's mention of AspectJ is more the way to go (but I'm not sure that can work with Kotlin - I see some mentions, such as https://github.com/serpro69/kotlin-aspectj-maven-example/blob/master/README.md, but no idea if that actually works).
pragma solidity ^0.8.17;
contract Greeter {
string greeting;
function Greeter(string _greeting) public{
greeting=_greeting;
}
function greet() constant returns (string){
return greeting;
}
}
ERROR
ParserError: Expected '{' but got 'constant'
--> project:/contracts/greeter.sol:7:22:
|
7 | function greet() constant returns (string){
i am compiling solidity program but there is issue when compiling
In the new compiler versions (0.4.21 above) the constructor and constant keyword deleted. Now, you must use for:
constructor: the following statement for:
constructor([parameters]) { // your logic }
constant: it depends on function accessibility that you give, in this case will be external. It allows to print the string that you initialized.
You must change your original smart in this way:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Greeter {
string greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function greet() external view returns(string memory){
return greeting;
}
}
I've been following a new journey into solidity for about a month now, so far so good, however with the Interface I'm having a hard time understanding the difference between these 2 methods of implementing Interfaces.
I can clearly notice how useful the Interface is in the 2nd method, but not in the 1st method.
Method 1:
pragma solidity ^0.8.0;
interface ICounter {
function count() external view returns (uint256);
function addToCount() external;
}
contract myInterface is ICounter {
uint256 counter = 0;
function count() external view override returns (uint256) {
return counter;
}
function addToCount() override external {
counter++ ;
}
}
Method 2:
pragma solidity ^0.8.0;
contract myContract {
uint256 count =0;
function increment() external {
count++ ;
}
}
pragma solidity ^0.8.0;
interface ICounter {
function count() external view returns (uint256);
function increment() external;
}
contract myInterface {
function incrementCount(address _counter) external {
ICounter(_counter).increment();
}
function getCount(address _counter) external view returns (uint256) {
return ICounter(_counter).count();
}
}
Interfaces in Solidity are mostly used for interacting with contracts deployed on other address, as you show in the Method 2.
Example of storing the pointer to another contract (assuming that it implements the interface) in a variable:
pragma solidity ^0.8.0;
interface ICounter {
function increment() external;
}
contract MyContract {
ICounter counter;
constructor(address _counter) {
counter = ICounter(_counter);
}
function incrementCount() external {
counter.increment();
}
}
In the Method 1, your code uses the is keyword for inheritance, which could be described as "myInterface is child of ICounter".
But there's no way to explicitly state implementation of an interface - that "myInterface implements ICounter". As you can see, you need to use the override modifier on the addToCount() function to state that you're overriding the parent function - which doesn't suggest implementing an interface at all.
I wouldn't consider the Method 2 a bad practice, as it can help you remember to implement all intended functions - otherwise the contract is treated as abstract and cannot be deployed. But for me personally, it's the less preferred method because there's no way to state an implementation instead of an inheritance (at least not in the current Solidity version 0.8).
Note: I'm aware that for example OpenZeppelin uses the Method 1 of "inheriting from an interface". I just don't agree with their approach.. :)
so I'm trying out an example of using a constructor with inheritance but the remix ide is returning an error, which isn't the case on the course I'm following. Any idea of what might be causing the error or if there's an update with the newer solidity versions?
pragma solidity ^0.8.0;
contract myConstruct {
string public name;
constructor(string memory _name) {
name = _name;
}
}
contract mySecondConstruct is myConstruct {
constructor (string memory _name) myConstruct(_name) {} ;
}
The semicolon ; doesn't belong after the block. (Empty block in your case {})
Correct syntax:
// remove the semicolon
constructor (string memory _name) myConstruct(_name) {}
So I wanted to isolate controllers from models in testing so that I could easily figure out stuff if troubles arise. Before, I just hit the endpoints with mock data but it was difficult to troubleshoot because the test runs from the router all the way to the datastore. So I'm thinking maybe I'll just create two versions(MockController vs Controller) for each controller(and model) and use one depending on the value of the mode variable. In a nutshell, this is how I plan to implement it.
const mode string = "test"
// UserModelInterface is the Interface for UserModel
type UserModelInterface interface {
Get()
}
// UserControllerInterface is the Interface for UserController
type UserControllerInterface interface {
Login()
}
// NewUserModel returns a new instance of user model
func NewUserModel() UserModelInterface {
if mode == "test" {
return &MockUserModel{}
} else {
return &UserModel{}
}
}
// NewUserController returns a new instance of user controller
func NewUserController(um UserModelInterface) UserControllerInterface {
if mode == "test" {
return &MockUserController{}
} else {
return &UserController{}
}
}
type (
UserController struct {um UserModelInterface}
UserModel struct {}
// Mocks
MockUserController struct {um UserModelInterface}
MockUserModel struct {}
)
func (uc *UserController) Login() {}
func (um *UserModel) Get() {}
func (uc *MockUserController) Login() {}
func (um *MockUserModel) Get() {}
func main() {
um := NewUserModel()
uc := NewUserController(um)
}
This way I could just skip sql query in the MockUserController.Login() and only validate the payload and return a valid response.
What do you think of this design? Do you have a better implementation in mind?
I would let the code that calls NewUserController() and NewUserModel() decide whether to create a mock or real implementation. If you use that pattern of dependency injection all the way up to the top your code will become clearer and less tightly coupled. E.g. if the user controller is used by a server, it would look something like along the lines of:
Real:
u := NewUserController()
s := NewServer(u)
In tests:
u := NewMockUserController()
s := NewServer(u)
I would try a more slim variant spread over a models and a controllers package, like this:
// inside package controllers
type UserModel interface {
Get() // the methods you need from the user model
}
type User struct {
UserModel
}
// inside package models
type User struct {
// here the User Model
}
// inside package main
import ".....controllers"
import ".....models"
func main() {
c := &controllers.User{&models.User{}}
}
// inside main_test.go
import ".....controllers"
type MockUser struct {
}
func TestX(t *testing.T) {
c := &controllers.User{&MockUser{}}
}
For controller testing consider the ResponseRecorder of httptest package