OOP in Python, specially Composition
So, I've been trying to get my hands-on experience on Python and this OOP concept just started coming along. I can't seem to understand the concept of Composition clearly with good examples like a car example. Any help on this would be great!
I'll provide a code which uses Composition, Can anyone explain the use of Composition here?
class Clothing:
stock={ 'name': [],'material' :[], 'amount':[]}
def __init__(self, name):
material = ""
self.name = name
def add_item(self, name, material, amount):
Clothing.stock['name'].append(self.name)
Clothing.stock['material'].append(self.material)
Clothing.stock['amount'].append(amount)
def Stock_by_Material(self, material):
count=0
n=0
for item in Clothing.stock['material']:
if item == material:
count += Clothing.stock['amount'][n]
n+=1
return count
class shirt(Clothing):
material="Cotton"
class pants(Clothing):
material="Cotton"
polo = shirt("Polo")
sweatpants = pants("Sweatpants")
polo.add_item(polo.name, polo.material, 4)
sweatpants.add_item(sweatpants.name, sweatpants.material, 6)
current_stock = polo.Stock_by_Material("Cotton")
print(current_stock)
See also questions close to this topic
-
Tabulate Spherical Harmonic Functions
Hey I am trying to express the spherical harmonics in a compact way. I can not figure out how to express this in a table I got the spherical Harmonics for l = 0,1,2 and m = -l, ...,+l in a list. But wanted a Table in the form:
m -2 -1 0 1 2 l 0 x 1 x x x 2 x x x x x
Does anyone know how to do this since I only worked out to create simpler tables with tabulate using with normal headers. I have got the functions in the list sph_harmonics[].
from sympy import Ynm from tabulate import tabulate sph_harmonics = [] for l in range (0, 3): for m in range(-l, l+1): print('l =', l) print('m =',m) print(sp.simplify(Ynm(l, m, theta, phi).expand(func=True))) sph_harmonics.append(sp.simplify(Ynm(l, m, theta, phi).expand(func=True)))
-
How to convert object string to int?
i have a dataframe with object type on it, i need to make it type be an integer, so i can convert it to float. I already try to loop it and change with if else condition, but it makes another problem, what i must to do? thank's before.
for x in df_merge3["type"]: if x == 'course': df_merge3[["type"][x]] = 1 elif x == exercise: df_merge3[["type"][x]] = 2 elif x == challange: df_merge3[["type"][x]] = 3 elif x == achievement: df_merge3[["type"][x]] = 4 print(x)
-
adding an auth check to github webhooks using flask + python3
I've been trying to add auth to github but for some reason my hashes don't match,
here is my code:
@app.route('/update', methods=["POST"]) def update(): assert request.method == "POST" signature = request.headers.get("X-Hub-Signature") if not signature or not signature.startswith("sha1="): abort(400, "X-Hub-Signature required") sha_name, sinature = signature.split("=") if sha_name != "sha1": abort(501) # Create local hash of payload digest = hmac.new(github_secret.encode(), msg=request.data, digestmod="sha1").hexdigest() # Verify signature if not hmac.compare_digest(signature, digest): abort(400, "Invalid signature")
-
Google cloud - delete bucket metadata
trying to delete metadata on an object in a google cloud bucket.
the docs only so an example when using the json api, in which is says to send metadata-key:null.
I have tried this using python below, but all this does is replace metadata-data with "null" as a string instead of deleting it.
how do you actually delete metadata using the api/gsutil
i have tried gsutil setmeta also, its easy to edit the metadata, but i cant seem to delete it..
https://cloud.google.com/storage/docs/viewing-editing-metadata
import os f
from google.cloud import storage bucket_name = "bucket-name" blob_name = "blobname" def set_blob_metadata(bucket_name, blob_name): storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) blob = bucket.get_blob(blob_name) metadata = {'x-goog-meta-key':"null"} blob.metadata = metadata blob.patch() print("The metadata for the blob {} is {}".format(blob.name, blob.metadata)) set_blob_metadata(bucket_name, blob_name)
-
Image not showing properly when reading the image using PIL instead of imagio library
I have this code that converts an image from RGB space to HSI space:
import numpy as np import imageio from matplotlib import pyplot as plt def RGB_TO_HSI(img): with np.errstate(divide='ignore', invalid='ignore'): rgb = np.float32(img) / 255 # Separate color channels red = rgb[:, :, 0] green = rgb[:, :, 1] blue = rgb[:, :, 2] # Calculate Intensity def calc_intensity(red, green, blue): intensity = (red + green + blue + 0.001) / 3 return intensity # Calculate Saturation def calc_saturation(red, green, blue): minimum = np.minimum(np.minimum(red, green), blue) saturation = 1 - (minimum / calc_intensity(red, green, blue)) return saturation # Calculate Hue def calc_hue(red, green, blue): hue = np.copy(red) # Basically have our hue = red for now; we only need its size/dimensions for i in range(0, blue.shape[0]): for j in range(0, blue.shape[1]): if blue[i][j] <= green[i][j]: hue[i][j] = np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / (np.sqrt((red[i][j] - green[i][j]) ** 2 + (red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j])))) else: hue[i][j] = 2 * np.pi - np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / (np.sqrt((red[i][j] - green[i][j]) ** 2 + (red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j])))) return hue # Merge channels into picture and return image hsi = np.zeros(img.shape) # instead of having 3 channels, one for each color (RGB), here we have a channel; for "hue", another for "saturation" and another for "intensity" hsi[:, :, 0], hsi[:, :, 1], hsi[:, :, 2] = calc_hue(red, green, blue), calc_saturation(red, green, blue), calc_intensity(red, green, blue) return hsi cat = imageio.imread("Path...") hsi_cat = RGB_TO_HSI(cat) plt.imshow(hsi_cat) plt.show()
However, adjusting the line in the code to:
hsi = np.zeros(rgb.shape, dtype=np.uint8)
, then loading the image using PIL, and passing it into the function as an argument:cat_p = Image.open("Path...") # Using PIL now his_cat_p = RGB_TO_HSI(cat_p) # Passing the JPEG image into the function his_cat_p = Image.fromarray(his_cat_p) # Converting the result back from an array (return hsi), into JPEG format his_cat_p.show() # Black image appears
This results is a black image, and I'm not quite sure why!
-
Maintaining global but changeable variables across classes/packages
I want to maintain some global variables that can be changed in Java. And once the state/value of a variable changes, next time I use this variable I should have the new changed state/value.
For example I use a config property and once changed, the new value should be used thereafter.
I am not able to figure out how to achieve this in Java. Any suggestions would be very helpful.
-
UML, OOP(JAVA, C++) , GUI
I am try to connect the dots learning about how to: UML, OOP(Java/C++), GUI. To develop (Android/PC) applications.
I started to watch tutorials, read online articles about the fields, however, i can not find a clear way how to convert one to another, as well as how the process is done in parallel.
Can you help me with some tips for each field ? Thank you for your time and attention.
Hence: I really want to learn all the above mentioned skills because it will help me to improvise.
-
how i made this managment in java plz answer me hurry?
A. Video Game Management System in which you will have to create following classes: i. Video Game Company (has video game) ii. Video Game (has platform) iii. Platform iv. Gamer (has video game)
B. Football Management System in which you will have to create following classes: i. Team (has matches) ii. Match (has a venue) iii. Venue iv. Player (has a team)
You have to create at least two significant new classes in each system that will be sub classes of any one of the given classes in system also add at least one abstract method in super class.
-
how to stop form submitting if form is invalid in vue3 cli compostion apis in vee validate
i am new to vue3 and composition apis. there is problem with validating a simple form. i am trying to stop form submission if form is not valid or not touched as it is vaild by default if inputs not touched.
login.vue
<form @submit="onSubmit"> <div class="form-group"> <input name="email" type="text" v-model="email" /> <span>{{ emailError }}</span> </div> <div class="form-group"> <input name="password" type="password" v-model="password" /> <span>{{ passwordError }}</span> </div> <div class="login-buttons"> <button type="submit" > {{ $t("login.login") }} </button> </div> </form>
login.js
<script> import { useForm, useField,useIsFormValid } from "vee-validate"; import * as yup from "yup"; export default { name: "LoginPage", setup() { const { errors, handleSubmit, validate, } = useForm(); // Define a validation schema const schema = yup.object({ email: yup .string() .required() .email(), password: yup .string() .required() .min(8), }); // Create a form context with the validation schema useForm({ validationSchema: schema, }); // No need to define rules for fields const { value: email, errorMessage: emailError } = useField( "email" ); const { value: password, errorMessage: passwordError } = useField( "password" ); const onSubmit = handleSubmit(async () => { const { valid, errors } = await validate(); if (valid.value === false) { return; } else { const response = await http.post(APIs.login, data); } }); return { email, emailError, password, passwordError, onSubmit }; }, }; </script>
in handelSubmit function if (vaild.value === false) it should return and stop the logic but always the value for vaild is true so it continues the HTTP calling for the api.
only wan't to stop sending data to the if the form is invaild using composition apis
-
Best practice to avoid duplication of methods in two classes using a list of objects of another class?
This a bit like the inheritance and composition discussion but here we have a list of objects. The problem: I have two classes GuidedTour and TourGuide both having a list of DateRange objects. I want to avoid duplicating methods operating on the DateRange objects like add_date_ranges, get_date_ranges, count_date_ranges, etc.
class DateRange: def __init__(self, date_from, date_last): self.date_from = date_from self.date_last = date_last class GuidedTour: def __init__(self): self.date_ranges = [] def add_date_range(self, date_from, date_last): self.date_ranges.append(DateRange(date_from, date_last)) class TourGuide: def __init__(self): self.date_ranges = [] def add_date_range(self, date_from, date_last): self.date_ranges.append(DateRange(date_from, date_last))
Two ways to solve this.
- Inheritance. Create a class TourDateRanges inherited by both the GuidedTour and TourGuide classes with all methods operating on the DateRange objects.
class DateRange: def __init__(self, date_from, date_last): self.date_from = date_from self.date_last = date_last class TourDateRanges: def add_date_range(self, date_from, date_last): self.date_ranges.append(DateRange(date_from, date_last)) class GuidedTour(TourDateRanges): def __init__(self): self.date_ranges = [] class TourGuide(TourDateRanges): def __init__(self): self.date_ranges = []
Now I can do:
date_from = '2021-08-01' date_last = '2021-08-31' guided_tour = GuidedTour() guided_tour.add_date_range(date_from, date_last)
- Composition. Create a class TourDateRange as above but this time this class is added to the GuidedTour and TourGuide classes.
class DateRange: def __init__(self, date_from, date_last): self.date_from = date_from self.date_last = date_last class TourDateRanges: def __init__(self): self.date_ranges = [] def add_date_range(self, date_from, date_last): self.date_ranges.append(DateRange(date_from, date_last)) class GuidedTour: def __init__(self): self.tour_date_ranges = TourDateRanges() class TourGuide: def __init__(self): self.tour_date_ranges = TourDateRanges()
Now I can do:
date_from = '2021-08-01' date_last = '2021-08-31' guided_tour = GuidedTour() guided_tour.tour_date_ranges.add_date_range(date_from, date_last)
I prefer the composition option, but I'm not sure I'm right and maybe there are other ways to solve this.
-
Is there any way to call constructor of child class using object of parent class in JAVA?
I have a problem in composition in Java. I want to access the constructor of a class located inside another class. Now if I made an object of parent class and want to access constructor of child class. Is there any possible way to do it?
Here's the code of the both classes and runner class.
package compositon.student; public class phone { String countryCode; String number; public phone(){}//empty constructor public phone(String countryCode, String number) { this.countryCode = countryCode; this.number = number; } }
package compositon.student; public class address { String Street_address; String town; String city; String country; phone number = new phone(); //object from class phone, by using composition of classes public static void main(String[] args) { address objAddress = new address(); objAddress.number() } }
-
What is the correct way to access a class composite inside one of its components, if that's even advisable?
Suppose I have these two classes:
class Branch(): def __init__(self, id, leaves): self.id = id self.leaves = leaves class Leaf(): def __init__(self, color) self.color = color def describe() print("This leaf is " + color)
Every
Leaf
belongs to aBranch
. ABranch
continues to exist whether it has any leaves or not, but aLeaf
cannot meaningfully exist without aBranch
(real-life logic aside). That means I can easily get everyLeaf
from aBranch
through theBranch.leaves
attribute. If I understood composition correctly, aBranch
is the composite and everyLeaf
inBranch.leaves
is one of its components?However, no
Leaf
actually knows to whichBranch
it belongs to. So, I can't have it print "This leaf is orange and belongs to branch #14". I could just add aLeaf.branch
attribute and pass it whenever I initialize a newLeaf
instance, seeing how aBranch
must already exist for that to happen, but that seems very wrong to me, because then it looks like theBranch
belongs to theLeaf
.The question is: what is the most pythonic and correct way to do what I described I can't do in my example? Is what I thought felt very wrong not actually bad at all? Or rather, did this problem arise from bad design and I should look at this from another angle? Thanks in advance.
-
Providing an example of composition for these classes
Trying to learn more about concepts in C#. Would anyone be able to explain how composition could be used between these two classes:
class Book { string Title; string Author; string Year; public Book(string Title, string Author, string Year) { this.Title = Title; this.Author = Author; this.Year = Year; } public void Display() { Console.WriteLine(Title + " " + Author); } } class BookTest { public static void Main(string[] args) { Book test = new Book("Anna Karenina", "Leo Tolstoy", "1878"); test.Display(); } } }
-
LNK2019 Unresolved external symbol while composing two classes into one
I have created two classes Name and Date to use it in another class LibraryBook, but the code gives me an unresolved external symbol. I am compiling this code in Visual Studio 2019.
The name class stores a first name and a last name. The date class stores date in DD-MM-YYYY format. The Library book class has following attributes:
char* const ISBN; // stores the ISBN of the book char* title; // stores the title of the book const Name author; // stores the name of author Name publisher; // stores the name of publisher int quantity; // stores the quantitiy of book Date lastIssue; // stores the latest issue date of the book.
The unresolved externals I am getting are:
1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: __thiscall Date::Date(class Date const &)" (??0Date@@QAE@ABV0@@Z) referenced in function "public: __thiscall LibraryBook::LibraryBook(char * const,char *,class Name,class Name,class Date,int)" (??0LibraryBook@@QAE@QADPADVName@@2VDate@@H@Z) 1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: void __thiscall Date::showDate(void)const " (?showDate@Date@@QBEXXZ) referenced in function "public: void __thiscall LibraryBook::displayBookDetails(void)" (?displayBookDetails@LibraryBook@@QAEXXZ) 1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: __thiscall Date::~Date(void)" (??1Date@@QAE@XZ) referenced in function "public: __thiscall LibraryBook::LibraryBook(char * const,char *,class Name,class Name,class Date,int)" (??0LibraryBook@@QAE@QADPADVName@@2VDate@@H@Z) 1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: __thiscall Name::Name(class Name const &)" (??0Name@@QAE@ABV0@@Z) referenced in function "public: __thiscall LibraryBook::LibraryBook(char * const,char *,class Name,class Name,class Date,int)" (??0LibraryBook@@QAE@QADPADVName@@2VDate@@H@Z) 1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: __thiscall Name::~Name(void)" (??1Name@@QAE@XZ) referenced in function "public: __thiscall LibraryBook::LibraryBook(char * const,char *,class Name,class Name,class Date,int)" (??0LibraryBook@@QAE@QADPADVName@@2VDate@@H@Z) 1>LibraryBook.obj : error LNK2019: unresolved external symbol "public: char * __thiscall Name::fullName(void)" (?fullName@Name@@QAEPADXZ) referenced in function "public: void __thiscall LibraryBook::displayBookDetails(void)" (?displayBookDetails@LibraryBook@@QAEXXZ)
Name.h
#pragma once #include<iostream> using namespace std; class Name { public: Name(char* = nullptr, char* = nullptr); //parametrized constructor with default arguments Name(const Name&); // copy constructor ~Name(); // destructor (should release all dynamic allocations) void copyName(Name&); //this is not a copy constructor, I want this function to copy the contents of //one name(firstName and lastName both) to another name. // Function copies the contents of the calling object to the passing object. i.e... // ...name.firstNamee = this->firstName and name.lastName = this->lastName // The function will copy the contents of the calling object to the passing object. void camelCase(); // make first letter capital of both attributes void toLower(); // convert name to lower case alphabets void toUpper(); // convert name to upper case alphabets int nameLength(); // both first and last excluding space. Try for this name: Mohammad Hassan Zubair void swapName(); // firstName becomes lastName and vice versa void display(); // prints name(firstName and lastName with space in between) char* fullName(); // concatenate both attributes and return full name with a space in between both // provide setters/getters for Name class. Remember: setters with no memory leakage. // provide other relevant methods you want like your own strLength and strCopy function etc. // provide relevant methods for const objects too. void setFirstName(char* firstName); // no memory leakage char* getFirstName() const; // no memory leakage void setLastName(char* lastName); // no memory leakage char* getLastName() const; // no memory leakage //for const objects //void copyName(const Name&) const; // this method is not valid as a const object cannot be modified. void copyName(Name&) const; //this is not a copy constructor, I want this function to copy the contents of //one name(firstName and lastName both) to another name. // Function copies the contents of the calling object to the passing object. i.e... // ...name.firstNamee = this->firstName and name.lastName = this->lastName void camelCase() const; // make first letter capital of both attributes void toLower() const; // convert name to lower case alphabets void toUpper() const; // convert name to upper case alphabets int nameLength() const; // both first and last excluding space. //void swapName() const; // cannot modify attributes of a const function so no swapName for this function void display() const; // prints name(firstName and lastName with space in between) char* fullName() const; // concatenate both attributes and return full name with a space in between both // No setters and getters for a const object as it is const. private: char* firstName; char* lastName; bool isValidName(); // name should contain only alphabets - no special characters or digits int strLen(char*); // calculates the length of a string char* deepCopyArr(char* arr); int strLen(char*) const; // calculates the length of a string char* deepCopyArr(char* arr) const; };
Name.cpp
#include "Name.h" Name::Name(char* firstName, char* lastName) //parametrized constructor with default arguments { //firstName is neccessary for lastName. if (firstName) { this->firstName = deepCopyArr(firstName); if (lastName) { this->lastName = deepCopyArr(lastName); } else this->lastName = lastName; if (!isValidName()) //if name is invalid, nullptr is assigned to the name. { delete[] this->firstName; this->firstName = nullptr; delete[] this->lastName; this->lastName = nullptr; } } else { this->firstName = nullptr; this->lastName = nullptr; } } Name::Name(const Name& name) // copy constructor { //No need to check validation of name here as its callin object(name) cannot have an invalid name. //The calling object must have a valid name as it would have gone through the name-validation process in its constructor. if (name.firstName) { this->firstName = deepCopyArr(name.firstName); if (name.lastName) { this->lastName = deepCopyArr(name.lastName); } else this->lastName = name.lastName; } else { this->firstName = name.firstName; this->lastName = name.lastName; } } Name::~Name() { if (this->firstName) { delete[] this->firstName; this->firstName = nullptr; } if (this->lastName) { delete[] this->lastName; this->lastName = nullptr; } } void Name::copyName(Name& name) { // Function copies the contents of the calling object to the passing object. i.e... // ...name.firstNamee = this->firstName and name.lastName = this->lastName if (name.firstName) { delete[] name.firstName; name.firstName = nullptr; if (name.lastName) { delete[] name.lastName; name.lastName = nullptr; } } if (this->firstName) { name.firstName = deepCopyArr(this->firstName); if (this->lastName) { name.lastName = deepCopyArr(this->lastName); } else name.lastName = nullptr; } else { name.firstName = nullptr; name.lastName = nullptr; } } void Name::camelCase() // make first letter capital of both attributes { if (firstName) { int len_01 = strLen(firstName); //convert firstName to camel case here. if (firstName[0] >= 97 && firstName[0] <= 123) { firstName[0] -= 32; } for (int i = 1; i < len_01; i++) { if (firstName[i] >= 65 && firstName[i] <= 91) { firstName[i] += 32; } } if (lastName) //convert lastName to camelCase here. { int len_02 = strLen(lastName); if (lastName[0] >= 97 && lastName[0] <= 123) { lastName[0] -= 32; } for (int i = 1; i < len_01; i++) { if (lastName[i] >= 65 && lastName[i] <= 91) { lastName[i] += 32; } } } } } void Name::toLower() // convert name to lower case alphabets { if (this->firstName) { for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] >= 65 && this->firstName[i] <= 91) this->firstName[i] += 32; } if (this->lastName) { for (int i = 0; i < strLen(this->lastName); i++) { if (this->lastName[i] >= 65 && this->lastName[i] <= 91) this->lastName[i] += 32; } } } } void Name::toUpper() // convert name to upper case alphabets { if (this->firstName) { for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] >= 97 && this->firstName[i] <= 123) this->firstName[i] -= 32; } if (this->lastName) { for (int i = 0; i < strLen(this->lastName); i++) { if (this->lastName[i] >= 97 && this->lastName[i] <= 123) this->lastName[i] -= 32; } } } } int Name::nameLength() // both first and last excluding space. Try for this name: Mohammad Hassan Zubair { if (this->firstName && this->lastName) { return strLen(this->firstName) + strLen(this->lastName); } else if (this->firstName) { return strLen(this->firstName); } else return 0; } void Name::swapName() // firstName becomes lastName and vice versa { if (this->firstName && this->lastName) { char* temp_fN = deepCopyArr(this->lastName); char* temp_lN = deepCopyArr(this->firstName); delete[] this->firstName; this->firstName = temp_fN; delete[] this->lastName; this->lastName = temp_lN; } } void Name::display() { if (this->firstName) { cout << this->firstName; if (this->lastName) { cout << ' ' << this->lastName; } } } char* Name::fullName() // concatenate both attributes and return full name with a space in between both { if (this->firstName && this->lastName) { int length = strLen(this->firstName) + 1 + strLen(this->lastName); // I have used strLen() function various times instead of storing its result in a variable to avoid... //...buffer overrun. char* fullName = new char[length + 1]{ 0 }; for (int i = 0; i < strLen(this->firstName); i++) { fullName[i] = this->firstName[i]; } fullName[strLen(this->firstName)] = ' '; for (int i = 0; i < strLen(this->lastName); i++) { fullName[i + strLen(this->firstName) + 1] = this->lastName[i]; } return fullName; } else if (this->firstName) { return deepCopyArr(this->firstName); } else { return nullptr; } } int Name::strLen(char* arr) // calculates the length of a string { int length = 0; for (; arr[length] != '\0'; length++); return length; } bool Name::isValidName() // name should contain only alphabets - no special characters or digits { if (this->firstName) { for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] < 65 || this->firstName[i] > 91 && this->firstName[i] < 97 || this->firstName[i] > 123) return false; } if (this->lastName) { for (int i = 0; i < strLen(lastName); i++) { if (this->lastName[i] < 65 || this->lastName[i] > 91 && this->lastName[i] < 97 || this->lastName[i] > 123) return false; } } } return true; } char* Name::deepCopyArr(char* arr) //returns an arr to copy. { int length = strLen(arr); char* new_arr = new char[length + 1]{ '\0' }; for (int i = 0; i < length; i++) { new_arr[i] = arr[i]; } new_arr[length] = '\0'; return new_arr; } void Name::setFirstName(char* firstName) { this->firstName = deepCopyArr(firstName); if (!isValidName()) { delete[] this->firstName; this->firstName = nullptr; } } char* Name::getFirstName() const { if (this->firstName) return deepCopyArr(this->firstName); else return nullptr; } void Name::setLastName(char* lastName) { if (this->firstName) { this->lastName = deepCopyArr(lastName); if (!isValidName()) { delete[] this->lastName; this->lastName = nullptr; } } else this->lastName = nullptr; } char* Name::getLastName() const { if (this->lastName) return deepCopyArr(lastName); else return nullptr; } // For const objects int Name::strLen(char* arr) const // calculates the length of a string { int length = 0; for (; arr[length] != '\0'; length++); return length; } char* Name::deepCopyArr(char* arr) const //returns an arr to copy. { int length = 0; for (; arr[length] != '\0'; length++); char* new_arr = new char[length + 1]{ '\0' }; for (int i = 0; i < length; i++) { new_arr[i] = arr[i]; } new_arr[length] = '\0'; return new_arr; } void Name::camelCase() const // make first letter capital of both attributes { if (firstName) { int len_01 = strLen(firstName); if (firstName[0] >= 97 && firstName[0] <= 123) { firstName[0] -= 32; } for (int i = 1; i < len_01; i++) { if (firstName[i] >= 65 && firstName[i] <= 91) { firstName[i] += 32; } } if (lastName) { int len_02 = strLen(lastName); if (lastName[0] >= 97 && lastName[0] <= 123) { lastName[0] -= 32; } for (int i = 1; i < len_01; i++) { if (lastName[i] >= 65 && lastName[i] <= 91) { lastName[i] += 32; } } } } } void Name::toLower() const // convert name to lower case alphabets { if (this->firstName) { for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] >= 65 && this->firstName[i] <= 91) this->firstName[i] += 32; } if (this->lastName) { for (int i = 0; i < strLen(this->lastName); i++) { if (this->lastName[i] >= 65 && this->lastName[i] <= 91) this->lastName[i] += 32; } } } } void Name::toUpper() const // convert name to upper case alphabets { if (this->firstName) { for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] >= 97 && this->firstName[i] <= 123) this->firstName[i] -= 32; } if (this->lastName) { for (int i = 0; i < strLen(this->lastName); i++) { if (this->lastName[i] >= 97 && this->lastName[i] <= 123) this->lastName[i] -= 32; } } } } int Name::nameLength() const { if (this->firstName) { int length = 0; for (int i = 0; i < strLen(this->firstName); i++) { if (this->firstName[i] != 32) { length++; } } if (this->lastName) { for (int i = 0; i < strLen(this->lastName); i++) { if (this->lastName[i] != 32) { length++; } } } return length; } return 0; } void Name::display() const // prints name(firstName and lastName with space in between) { if (this->firstName) { cout << this->firstName; if (this->lastName) { cout << ' ' << this->lastName; } } } char* Name::fullName() const // concatenate both attributes and return full name with a space in between both { if (this->firstName && this->lastName) { int length = strLen(this->firstName) + 1 + strLen(this->lastName); // I have used strLen() function various times instead of storing its result in a variable to avoid... //...buffer overrun. char* fullName = new char[length + 1]{ 0 }; for (int i = 0; i < strLen(this->firstName); i++) { fullName[i] = this->firstName[i]; } fullName[strLen(this->firstName)] = ' '; for (int i = 0; i < strLen(this->lastName); i++) { fullName[i + strLen(this->firstName) + 1] = this->lastName[i]; } return fullName; } else if (this->firstName) { return deepCopyArr(this->firstName); } else { return nullptr; } } void Name::copyName(Name& name) const { // Function copies the contents of the calling object to the passing object. i.e... // ...name.firstNamee = this->firstName and name.lastName = this->lastName if (name.firstName) { delete[] name.firstName; name.firstName = nullptr; if (name.lastName) { delete[] name.lastName; name.lastName = nullptr; } } if (this->firstName) { name.firstName = deepCopyArr(this->firstName); if (this->lastName) { name.lastName = deepCopyArr(this->lastName); } else name.lastName = nullptr; } else { name.firstName = nullptr; name.lastName = nullptr; }
}
Date.h
#pragma once class Date { public: Date(); // initialize attributes with default values (01-01-2000) Date(int, int, int); // if invalid, set members equal to default values (01-01-2000) Date(const Date&); // A regular copy constructor bool inputDate(); // assign values to date attributes (cin from user), // return true if valid range of values are input else false bool copyDate(const Date&); // will behave similar to copy constructor bool inputCompleteDate(int, int, int); // will behave similar to parameterized constructor const Date& getDate() const; void retrieveDate(int&, int&, int&) const; // retrieve date attribute values using "pass by reference" void showDate() const; // Display date attribute values on Console bool isEqual(Date&) const; // return true if calling & passing date objects are equal *THIS POINTER* bool isLeapYear() const; ~Date(); // A regular destructor void setDay(int _day); int getDay(); void setMonth(int _month); int getMonth(); void setYear(int _year); int getYear(); private: bool validateDate() const; //const it. int day; int month; int year; };
Date.cpp
#include "Date.h" #include<iostream> using namespace std; Date::Date() // initialize attributes with default values (01-01-2000) { this->day = 01; this->month = 01; this->year = 01; } Date::Date(int day, int month, int year) // if invalid, set members equal to default values (01-01-2000) { this->day = day; this->month = month; this->year = year; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; } } Date::Date(const Date& date) // A regular copy constructor { //No need to check validation of date here as the object that calls the copy constructor will have a valid date. this->day = date.day; this->month = date.month; this->year = date.year; } bool Date::inputDate() // assign values to date attributes (cin from user), { cout << "Enter day: "; cin >> this->day; cout << "Enter month: "; cin >> this->month; cout << "Enter year: "; cin >> this->year; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; return false; } return true; } bool Date::copyDate(const Date& date) // will behave similar to copy constructor { //This function will always return true as its calling object(date) cannot have an invalid date. //The calling object must have a valid date as it would have gone through the date-validation process in its constructor. if (validateDate()) { this->day = date.day; this->month = date.month; this->year = date.year; return true; } else //This piece of code will never be exectued due to the reason I've stated above. { this->day = 1; this->month = 1; this->year = 2000; return false; } } bool Date::inputCompleteDate(int day, int month, int year) // will behave similar to parameterized constructor { this->day = day; this->month = month; this->year = year; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; return false; } return true; } void Date::retrieveDate(int& _day, int& _month, int& _year) const // retrieve date attribute values using "pass by reference" { _day = this->day; _month = this->month; _year = this->year; } void Date::showDate() const // Display date attribute values on Console { if (this->day < 10) { cout << '0'; } cout << this->day << '-'; if (this->month < 10) { cout << '0'; } cout << this->month << '-'; if (this->year < 10) { cout << "000"; } else if (this->year < 100 && this->year >= 10) { cout << "00"; } else if (this->year < 1000 && this->year >= 100) { cout << '0'; } cout << this->year; } bool Date::isEqual(Date& date) const // return true if calling & passing date objects are equal *THIS POINTER* { if (this->day == date.day && this->month == date.month && this->year == date.year) return true; return false; } bool Date::isLeapYear() const { if (year % 4 == 0) { if (year % 100 == 0) { if (year % 400 == 0) { return true; } else { return false; } } else return true; } else { return false; } } Date::~Date() // A regular destructor { this->day = 0; this->month = 0; this->year = 0; } void Date::setDay(int _day) { this->day = _day; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; } } int Date::getDay() { return this->day; } void Date::setMonth(int _month) { this->month = _month; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; } } int Date::getMonth() { return this->month; } void Date::setYear(int _year) { this->year = year; if (!validateDate()) { this->day = 1; this->month = 1; this->year = 2000; } } int Date::getYear() { return this->year; } bool Date::validateDate() const { bool isMoreDays = 0; bool _isLeapYear = isLeapYear(); if (month <= 7 && month % 2 != 0) isMoreDays = true; else if (month >= 8 && month % 2 == 0) isMoreDays = true; else isMoreDays = false; if (day <= 0) return false; if (day >= 32 && isMoreDays) return false; if (day >= 31 && !isMoreDays) return false; if (month == 2 && day >= 29 && !_isLeapYear) return false; if (month == 2 && day >= 30 && _isLeapYear) return false; if (month <= 0) return false; if (month >= 13) return false; if (year <= 0) return false; return true; } ///// Please read the following comment ///// /*Date& Date::getDate() const { There is no description provided in the function. Function will have no use as it is const and returning by reference at the same time. To make use of this function, consider the following code: static Date temp; //The object is static so that it won't be deleted when the scope of this function ends. temp.day = this->day; temp.month = this->month; temp.year = this->year; return temp; //Another way to make use of this code is by making it non-const or change it's return-type to const Date&. }*/ ///// Please read the comment above ///// const Date& Date::getDate() const { return *this; }
LibraryBook.h
#pragma once #include"Date.h" #include"Name.h" #include<iostream> using namespace std; class LibraryBook { public: LibraryBook(char* const, char*, Name, Name, Date, int); ~LibraryBook(); void displayBookDetails(); private: char* const ISBN; char* title; Name publisher; Name author; Date lastIssue; int quantity; char* deepCopyArr(char* arr); };
LibraryBook.cpp
#include "LibraryBook.h" char* LibraryBook::deepCopyArr(char* arr) //returns an arr to copy. { int length{ 0 }; for (; arr[length] != '\0'; length++); char* new_arr = new char[length + 1]{ '\0' }; for (int i = 0; i < length; i++) { new_arr[i] = arr[i]; } new_arr[length] = '\0'; return new_arr; } LibraryBook::LibraryBook(char* const _ISBN, char* _t, Name _p, Name _a, Date _lI, int _q) :ISBN(_ISBN),title(deepCopyArr(_t)),publisher(publisher = _p),author(author = _a),lastIssue(_lI),quantity(_q) { //stitle = deepCopyArr(_t); //quantity = _q; } LibraryBook::~LibraryBook() { // Destructor } void LibraryBook::displayBookDetails() { cout << "ISBN: " << ISBN << '\n'; cout << "Title: " << title << '\n'; cout << "Author: " << author.fullName() << '\n'; cout << "Publisher: " << publisher.fullName() << '\n'; cout << "Quantitiy: " << quantity << '\n'; cout << "Last Issue: "; lastIssue.showDate(); cout << '\n'; }