본문 바로가기
College Computer Science/Programming Langauages

[프로그래밍언어론] 과제 2 : OOP 특성을 가진 언어로 구현하기 (Go 사용)

by 2den 2020. 12. 20.
728x90

문제

Write a corresponding program for the given example below (in C++, Java and Python) using ONE of the other languages that have different OOP traits such as separation of types from their implementations (e.g. Go), multimethods (e.g. Julia), implementation-only inheritance thru mixin (e.g. Scala, Crystal), prototypes and delegation (e.g. Lua, Io), etc. You will be given better score if you can make the traits shine by articulating them. In order for that purpose, you can extend or revise the given programs appropriately. You can ignore some details such as how to obtain current date. Just stick to the key concepts.

 

C++, Java, Python으로 작성된 다음 프로그램을 다른 OOP 특성을 가진 언어 가운데 하나로 구현하시오. 다른 특성의 사례는 형과 구현을 구별하는 Go, 멀티메서드를 지원하는 Julia, 믹스인을 사용하여 구현만 상속하는 Scala Crystal, 클래스 대신 프토로타입/위임을 사용하는 Lua, Io 등이 있습니다. 이런 특성을 강조하여 돋보이게 할수록 가산점을 받을 것입니다. 이를 위하여 주어진 프로그램을 적당히 확장하거나 개정할 수도 있습니다. 날짜를 확인하는 것과 같은 구체적인 사항은 무시해도 좋습니다. 핵심 원칙에 충실하기 바랍니다.

 

* 문제의 취지는 한 번도 사용해보지 않은 언어로 해당 언어의 특징을 살려 프로그래밍을 하는 것!

 

//Member.cxx

#include <iostream>
#include <time.h>
#include <list>
#include <sstream>
#include <iomanip>
#include <iterator>

using namespace std;

// Class Date
inline int max(int a, int b)
{
    if (a > b) return(a); else return (b);
}

inline int min(int a, int b)
{
    if (a > b) return(b); else return (a);
}

class Date
{
public:
    Date();
    Date(int yr, int mn, int dy);
    int Year();
    int Month();
    int Day();
    ~Date();
    string Greet();
    friend Date Now();
private:
    int month, day, year;
    int DaysSoFar();
};

Date::Date()
{
   month = day = year = 1;
}

Date::Date(int yr, int mn, int dy)
{
   static int length[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

   month = max(1, mn);
   month = min(month,12);

   day = max(1,dy);
   day = min(day, length[month]);

   year = max(1, yr);
}

Date Now()
{
    time_t theTime = time(NULL);
    struct tm *aTime = localtime(&theTime);
    return Date(aTime->tm_year + 1900, aTime->tm_mon + 1, aTime->tm_mday);
}

Date::~Date()
{
}

int Date::Year()
{
   return year;
}

int Date::Month()
{
   return month;
}

int Date::Day()
{
    return day;
}

string Date::Greet()
{
    stringstream buf;
    buf << to_string(this->Year()) << "-" << setw(2) << setfill('0')
        << to_string(this->Month()) << "-"
        << to_string(this->Day());
    return buf.str();
}
// End of Class Date

class Member
{
public:
    string Name();
    int Age();
    virtual string Greet();
protected:
    Member(string name, Date birthdate);
private:
    string name;
    Date birthdate;
};

Member::Member(string name, Date birthdate)
{
    this->name = name;
    this->birthdate = birthdate;
}

string Member::Name()
{
    return this->name;
}

int Member::Age()
{
    return Now().Year() - this->birthdate.Year();
}

string Member::Greet()
{
    return "Name: " + this->Name() + ", Age: " + std::to_string(this->Age());
}

class Teacher: public Member
{
public:
    Teacher(string name, Date birthdate, string teaches);
    string Teaches();
    string Greet();
private:
    string lecture;
};

Teacher::Teacher(string name, Date birthdate, string teaches): Member(name, birthdate)
{
    this->lecture = teaches;
}

string Teacher::Teaches()
{
    return this->lecture;
}

string Teacher::Greet()
{
    return Member::Greet() + ", Teaches: " + this->Teaches();
}

class Student: public Member
{
public:
    Student(string name, Date birthdate, int id_no);
    int ID_no();
    string Greet();
private:
    int id_no;
};

Student::Student(string name, Date birthdate, int id_no): Member(name, birthdate)
{
    this->id_no = id_no;
}

int Student::ID_no()
{
    return this->id_no;
}

string Student::Greet()
{
    return Member::Greet() + ", ID_no: " + std::to_string(this->ID_no());
}

class Visiting: public Student
{
public:
    Visiting(string name, Date birthdate, int id_no, Date valid_thru);
    bool Expired();
    string Greet();
private:
    Date valid_thru;
    bool expired;
};

Visiting::Visiting(string name, Date birthdate, int id_no, Date valid_thru): Student(name, birthdate, id_no)
{
    this->valid_thru = valid_thru;
}

bool Visiting::Expired() // Buggy...
{
    Date now = Now();
    return now.Year() >= valid_thru.Year();
}

string Visiting::Greet()
{
    return Student::Greet() + ", Valid_thru: " + valid_thru.Greet();
}

// Sorters
bool ageComp(Member *m1, Member *m2)
{
    return m1->Age() < m2->Age();
}

bool reverseNameComp(Member *m1, Member *m2)
{
    return m1->Name().compare(m2->Name()) > 0;
}

int main(int argc, char *argv[])
{
    list<Member*> members;
    members.push_back(new Teacher("Harry", Date(1971, 12,  7), "Programming Languages"));
    members.push_back(new Teacher("Natasha", Date(1975,  9, 21), "Forbidden Archeology"));
    members.push_back(new Student("YK", Date(1999,  3, 16), 2051));
    members.push_back(new Student("SH", Date(2000, 10,  5), 4968));
    members.push_back(new Visiting("Alice", Date(1995, 7, 14), 9595, Date(2019, 12, 25)));
    members.push_back(new Visiting("Vanessa", Date(1998, 3, 27), 9598, Date(2019, 2, 28)));

    cout << "A few CAU members..." << endl;
    list<Member*>::iterator it;
    for (it = members.begin(); it != members.end(); ++it) {
        Member *member = *it;
        cout << member->Greet() << endl;
    }
    cout << endl;

    members.sort(ageComp);
    cout << "Members sorted on age..." << endl;
    for (it = members.begin(); it != members.end(); ++it) {
        Member *member = *it;
        cout << member->Greet() << endl;
    }
    cout << endl;

    members.sort(reverseNameComp);
    cout << "Members reverse sorted on name..." << endl;
    for (it = members.begin(); it != members.end(); ++it) {
        Member *member = *it;
        cout << member->Greet() << endl;
    }

    return 0;
}
// Member.java
import java.lang.System;
import java.util.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

interface HasNameAge
{
    public String name();
    public int age();
}

interface Greeter extends HasNameAge
{
    public String greet();
}

class Member implements Greeter
{
    protected Member(String name, LocalDate birthdate) {
        this.name = name;
        this.birthdate = birthdate;
    }

    public final String name() {
        return this.name;
    }

    public int age() {
        return LocalDate.now().getYear() - birthdate.getYear();
    }

    public String greet() {
        return "Name: " + this.name() + ", Age: " + this.age();
    }

    private String name;
    private LocalDate birthdate;
}

class Teacher extends Member
{
    public Teacher(String name, LocalDate birthdate, String teaches) {
        super(name, birthdate);
        this.lecture = teaches;
    }

    public String teaches() {
        return this.lecture;
    }

    public String greet() {
        return super.greet() + ", Teaches: " + this.teaches();
    }

    private String lecture;
}

class Student extends Member
{
    public Student(String name, LocalDate birthdate, int id_no) {
        super(name, birthdate);
        this.id_no = id_no;
    }

    public int ID_no() {
        return this.id_no;
    }

    public String greet() {
        return super.greet() + ", ID_no: " + this.ID_no();
    }

    private int id_no;
}

class Visiting extends Student
{
    public Visiting(String name,
            LocalDate birthdate, int id_no, LocalDate valid_thru) {
        super(name, birthdate, id_no);
        this.valid_thru = valid_thru;
    }

    public boolean expired() {
        return LocalDate.now().isAfter(this.valid_thru);
    }

    public String greet() {
        return super.greet() + ", Valid thru " +
               valid_thru.format(DateTimeFormatter.ofPattern("YYYY-MM-dd"));
    }

    private LocalDate valid_thru;
}

class AgeSorter implements Comparator<HasNameAge>
{
    public int compare(HasNameAge m1, HasNameAge m2) {
        return m1.age() - m2.age();
    }
}

class ReverseNameSorter implements Comparator<HasNameAge>
{
    public int compare(HasNameAge m1, HasNameAge m2) {
        return m2.name().toLowerCase().compareTo(m1.name().toLowerCase());
    }
}

public class Main
{
    public static void main(String[] args) {
        AbstractList<Greeter> greeters = new LinkedList<Greeter>();
        greeters.add(new Teacher("Harry", LocalDate.of(1971, 12,  7), "Programming Languages"));
        greeters.add(new Teacher("Natasha", LocalDate.of(1975,  9, 21), "Forbidden Archeology"));
        greeters.add(new Student("YK", LocalDate.of(1999,  3, 16), 2051));
        greeters.add(new Student("SH", LocalDate.of(2000, 10,  5), 4968));

        Greeter Alice = new Visiting("Alice", LocalDate.of(1995, 7, 14), 9595,
            LocalDate.of(2019, 12, 25));
        Greeter Vanessa = new Visiting("Vanessa", LocalDate.of(1998, 3, 27), 9598,
            LocalDate.of(2019, 2, 28));
        greeters.add(Alice);
        greeters.add(Vanessa);

        System.out.println("A few CAU greeters...");
        for (Greeter greeter: greeters)
            System.out.println(greeter.greet());
        System.out.println();

        Collections.sort(greeters, new AgeSorter());
        System.out.println("Members sorted on age...");
        for (Greeter greeter: greeters)
            System.out.println(greeter.greet());
        System.out.println();

        Collections.sort(greeters, new ReverseNameSorter());
        System.out.println("Members reverse sorted on name...");
        for (Greeter greeter: greeters)
            System.out.println(greeter.greet());
    }
}
#Member.py
from datetime import date

class Member(object):
    def __init__(self, name, birthdate):
        self._name = name
        self._birthdate = birthdate

    def name(self):
        return self._name

    def age(self):
        # Naive and buggy
        return date.today().year - self._birthdate.year

    def greet(self):
        return f'Name: {self.name()}, Age: {self.age()}'

class Teacher(Member):
    def __init__(self, name, birthdate, teaches):
        super().__init__(name, birthdate)
        self._lecture = teaches

    def teaches(self):
        return self._lecture

    def greet(self):
        return f'{super().greet()}, Teaches: {self.teaches()}'

class Student(Member):
    def __init__(self, name, birthdate, id_no):
        super().__init__(name, birthdate)
        self._id_no = id_no

    def ID_no(self):
        return self._id_no

    def greet(self):
        return f'{super().greet()}, ID_no: {self.ID_no()}'

# Adding a new class under Student
class Visiting(Student):
    def __init__(self, name, birthdate, id_no, valid_thru):
        super().__init__(name, birthdate, id_no)
        self._valid_thru = valid_thru

    def greet(self):
        return f'{super().greet()}, Valid thru {self._valid_thru}'

    def expired(self):
        today = date.today()
        return today > self._valid_thru

members = [
    Teacher('Harry', date(1971, 12, 7), "Programming Languages"),
    Teacher('Natasha', date(1975, 9, 21), "Forbidden Archeology"),
    Student('YK', date(1999, 3, 16), 2051),
    Student('SH', date(2000, 10, 5), 4968),
    Visiting('Alice', date(1995, 7, 14), 9595, valid_thru=date(2019, 12, 25)),
    Visiting('Vanessa', date(1998, 3, 27), 9598, valid_thru=date(2019, 2, 28))
]

print("A few CAU members...")
for member in members:
    print(member.greet())
print()

members_sorted_on_age = sorted(members, key=lambda m: m.age())
print("Members sorted on age...")
for member in members_sorted_on_age:
    print(member.greet())
print()

members_sorted_on_name = sorted(members, key=lambda m: m.name().lower(), reverse=True)
print("Members sorted in reverse on name...")
for member in members_sorted_on_name:
    print(member.greet())

 


Member.go

package main

import (
  "fmt"
  "time"
  "sort"
  "strings"
  "strconv"
)

//types

type Member struct {
  name string
  birthdate [3]int
}

type Teacher struct {
  Member
  teaches string
}

type Student struct {
  Member
  id_no int
}

type Visiting struct {
  Student
  valid_thru [3]int
}

type NameAge interface {
  Name() string
  Age() int
}

type Greeting interface {
  NameAge
  Greet() string
}

// methods

func (member Member) Name() string {
  return member.name
}

func (member Member) Age() int {
  return time.Now().Year() - member.birthdate[0]
}

func (member Member) Greet() string {
  return "Name : " + member.name + ", Age : " + strconv.Itoa(member.Age())
}

func (teacher Teacher) Greet() string {
  return teacher.Member.Greet() + ", Teaches : " + teacher.teaches
}

func (student Student) Greet() string {
  return student.Member.Greet() + ", ID_no : " + strconv.Itoa(student.id_no)
}

func (visiting Visiting) Greet() string {
  return visiting.Student.Greet() + ", Valid thru " + strconv.Itoa(visiting.valid_thru[0]) + "." + strconv.Itoa(visiting.valid_thru[1]) + "." + strconv.Itoa(visiting.valid_thru[2]) + "(Expired : " + strconv.FormatBool(visiting.Expired()) + ")" // Expired 출력 추가
}

func (visiting Visiting) Expired() bool {
  vldthr := visiting.valid_thru[0]*10000 + visiting.valid_thru[1]*100 + visiting.valid_thru[2]
  now := time.Now().Year()*10000 + int(time.Now().Month())*100  + time.Now().Day()
  return now > vldthr
}

// entry point

func main() {
  members := make([]Greeting, 6)
  members[0] = Teacher{ Member{"Harry", [3]int{1971, 12, 7}}, "Programming Languages"}
  members[1] = Teacher{ Member{"Natasha", [3]int{1975, 9, 21}}, "Forbidden Archeology"}
  members[2] = Student{ Member{"YK", [3]int{1999, 03, 16}}, 2051}
  members[3] = Student{ Member{"SH", [3]int{2000, 10, 5}}, 4968}
  members[4] = Visiting{ Student{ Member{"Alice", [3]int{1995, 7, 14}}, 9595}, [3]int{2020, 12, 25}}
  members[5] = Visiting{ Student{ Member{"Vanessa", [3]int{1998, 3, 27}}, 9598}, [3]int{2020, 2, 28}}

  println("A few CAU members...")
  for _, element := range members {
    fmt.Printf("%s\n", element.Greet())
  }
  println()

  sort.Slice(members, func(i int, j int) bool {
    return members[i].Age() > members[j].Age()
  })
  println("Members sorted on age...")
  for _, element := range members {
    fmt.Printf("%s\n", element.Greet())
  }
  println()

  sort.Slice(members, func(i int, j int) bool {
    return strings.ToLower(members[i].Name()) > strings.ToLower(members[j].Name())
  })
  println("Members sorted in reverse on name...")
  for _, element := range members {
    fmt.Printf("%s\n", element.Greet())
  }
}

 

참고한 사이트:

 

예제로 배우는 Go 프로그래밍

쉽고 재미있는 Go 프로그래밍 예제로 배우는 Go 프로그래밍 I like a lot of the design decisions they made in the [Go] language. Basically, I like all of them. - Martin Odersky, Creator of Scala

golang.site


평가

교수님은 창의적인 구현을 추가하길 바라신 것 같긴 하지만, 주어진 코드 + 날짜 확인에 관해서는 Go의 특성을 살려 잘 코딩했다고 하셨음

 

728x90

댓글