Inheritance Programming Assignment

#21

I was wondering how does a new owner type in that he has a cat, how to push that and how to return it ?

function _addAnimal(string memory _name, uint _age, AnimalType _animalType) internal returns (uint){
return ownerToAnimals[msg.sender].push(Animal(_name, _age, _animalType)) - 1;
}

0 Likes

#22

Because _animalType has an input type of value so in this case you type in “filip”, 10, 1 , how does the user know from what type of animals to choose, is there any way to have an input as a string ?
thx

0 Likes

#24

@filip will help you as soon as he has time

0 Likes

#25

Ok thanks, Im just having a hard time about the enum being called from struct and that struct being mapped to an address :frowning: Maybe its a weird question but im just stuck here. I wrote my own contract as this is the best way I learn code and meaning of it .Here is the code …
pragma solidity 0.5.1;

contract Person{

  constructor ()public{
            
            owner = msg.sender ; 
            
            
            
        }
address owner ; 

enum Gender  {female, male}

struct Person {
    string name;
    string lastName;
    uint age;
    Gender varGender;
    
    
    
    
}

mapping (address => Person[]) mapPerson; 


function addPerson ( string memory _name, string memory _lname, uint _age, Gender _gender )  public returns (uint){
   return mapPerson[msg.sender].push(Person(_name, _lname, _age, _gender)) ; // how can an user select the gender , by typing jjust 0,1 ? 
    
}

      
   function callPerson (uint id)  view public returns (string memory){
       
      return  mapPerson[owner][id].; // how can a user print a gender ? 
       
   }    

}

Maybe im just not getting it… thanks :slight_smile:

0 Likes

#26

Hi @tinyHamster

I had modify a bit your sample to answer your questions you can find it bellow
When passing a gender to the addPerson function the number you pass should be existing in the enum:
An enum start from 0 and increments itself automatically, so for your Gender enum it will have only 0 and 1 available as gender.
addPerson -> “joe”,“foo”,20,1 //is correct
addPerson -> “sarah”,“bar”,24,0 //is correct
addPerson -> “egg”,“fried”,12,6 // will fail and trow an error “transact to PersonContract.addPerson errored: VM error: invalid opcode”

Because 6 is not define in your enum.

To display the available value of an enum you have different options the one i prefer is to add a “last” enum and to display the value of the last enum -1.
You can also hard code it in a string.

Let me know if you want more information and if i had answer your questions :wink:

pragma solidity 0.5.1;

contract PersonContract{

    constructor () public {
        owner = msg.sender ; 
    }
 
    address owner ; 

    /*
     * If you don't set a value to the first enum 
     * the value of the first enum will be zero
     * so in this case female ==0 and male==1
    */
    enum Gender  {female, male, notBinary, last}

    struct Person {
        string name;
        string lastName;
        uint age;
        Gender varGender;
    }

    mapping (address => Person[]) mapPerson; 


    function addPerson ( string memory _name, string memory _lname, uint _age, Gender _gender )  public returns (uint){
        require(_gender == Gender.female || _gender == Gender.male,
                 "Gender should be 0 for female and 1 for male");
        return mapPerson[msg.sender].push(Person(_name, _lname, _age, _gender))-1 ; // how can an user select the gender , by typing jjust 0,1 ? 
    }

    // Here we show that 2 is the maximum value female=0,male=1,notBinary=2
    function MaximumValueForGender() pure public returns(uint){
        return uint(Gender.last) - 1;
    }
    
    function showGendersWithString() pure public returns(string memory){
        return ("Directly write the option here: female=0,male=1,notBinary=2");
    }

    function callPersonGender (uint id)  view public returns (string memory){
        string memory gender;
        if (mapPerson[owner][id].varGender == Gender.male)
            gender = "male";
        else if (mapPerson[owner][id].varGender == Gender.female)
            gender = "female";
        return  gender; 
    }
}

Edit:

You can also use an input as a string but it ll cost more gas to compare the string passed as argument.

    function compareString(string memory _name) pure public returns(Gender){
        if(uint(keccak256(abi.encodePacked("male"))) == uint(keccak256(abi.encodePacked(_name)))) {
            return Gender.male;
        }else if(uint(keccak256(abi.encodePacked("female"))) == uint(keccak256(abi.encodePacked(_name)))) {
            return Gender.female;
        } else{
            return Gender.notBinary;
        }
    }

    function addPersonWithString ( string memory _name, string memory _lname, uint _age, string memory _gender )  public returns (uint){
        require(compareString(_gender) == Gender.notBinary,
                 "Gender should be 'male' or 'female'");
        return mapPerson[msg.sender].push(Person(_name, _lname, _age, compareString(_gender)))-1 ; 
    }
0 Likes

#27

my answer:


pragma solidity 0.5.1;

contract Ownable{

    address public owner;

    constructor() public{
        owner = msg.sender;
    }
    
    modifier onlyOwner(){
        require(msg.sender == owner);
        _;
    }

    function changeOwnership(address _newOwner) public onlyOwner{
        require(owner != _newOwner,
        "The address should be different than the last one");
        owner = _newOwner;
    }
}
0 Likes

#28

Hey, thanks for the help i was playing around with the code , so in the line" mapPerson[owner][id].varGender == Gender.male" , the “mapPerson[owner][id].varGender” is the locations in the array and the “Gender.male " is the value ? I was playing around with the code, is there a particular reason you went with " enum Gender {female, male, notBinary, last}” and not without the "last " in the array and just delete the -1 when called, it shows the 2 in both cases ?
Thanks, really appreciate the help :wink:

0 Likes

#29

Hey
So in mapPerson[owner][id].varGender:
The ‘owner’ is the address of the mapping we use to store a Person array.
The ‘id’ is the index where we store a Person structure (see that as an object) in the Person array.
Then we can access to all the element of this structure (or object) mapPerson[owner][id].name , mapPerson[owner][id].lastName, mapPerson[owner][id].age, mapPerson[owner][id].varGender.

I used Gender.last as a delimiter you are right i can remove the -1 and Gender.last it will return 2.
But in case of enum if i want to add let’s say :
enum Gender {female, male, notBinary, yellow, red, blue}
i will have to change my function with:

     function MaximumValueForGender() pure public returns(uint){
         return uint(Gender.blue) ;
     }

If i use Gender.last -1 i just change my enum not my function (it’s just a lazy way to do less lol)

0 Likes

#30

Could you clarify your question? The code in your post accomplishes almost all of that. You can’t however return a struct. So that’s why we return the position in the array.

0 Likes

#31

Yeah I see what u did there, hehe didn’t occur to me :smiley: "you gotta excuse my friend here, hes a little slow " :slight_smile: thanks for the help :slight_smile:

0 Likes

#32

pragma solidity 0.5.1;
contract Ownable{
address public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
constructor() public{
owner = msg.sender;
}

function ownerChange(address _newOwner) public onlyOwner(){
owner = _newOwner;
}
}

0 Likes

#33
    function setNewOwner(address _newOwner) public onlyOwner returns(address) {
        //creating a function called setNewOwner, taking an eth address as its parameter.
        //it is public because it needs to be accessible from the outside
        //onlyOwner modifier is used so that only the initial owner of the contract can call the function
        //the function should return the new owner's address
        return owner = _newOwner;
    }

@filip Hi, sorry to bother you, I have used a return in my function, as I thought it useful to return the new address. The behavior the contract is OK, but I was wondering whether there are side effects to doing this, as opposed to implementing it without the return? Thanks in advance for your help.

0 Likes

#34

Yes, that looks fine to me.

0 Likes

#35

function moveOwner(address newOwner) public onlyOwner {
// require(newOwner != address (0));
owner = newOwner;

}

1 Like

#36
pragma solidity 0.5.1;

contract Ownable{
    
    address public owner;
    
    modifier onlyOwner(){
          require (msg.sender == owner, "Only the owner of the contract can perform this task.");
        _;
    }
    
    constructor() public{
           owner = msg.sender;
    }
    
    function newOwner(address _address) public onlyOwner returns (address){
        owner = _address;
        return owner;
    }
}
1 Like

#37

Only the owner can specify a new owner. Require that it’s a different owner than the current owner.

function newOwner(address _newOwner) public onlyOwner{
    require(owner!=_newOwner);
    owner = _newOwner;
}
1 Like